From 1d7d0563fbdc327e9afe8d7a94495546940c1357 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Fri, 9 Sep 2022 12:36:44 +0200 Subject: [PATCH 001/144] [Security Solution][Threat Hunting] Add APM transactions for relevant user actions (#139843) * add timelines user-actions * custom fields and addToTimeline transactions * alerts buttons events * test fix * remove hover fields tracking and conditional fix Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/common/lib/apm/user_actions.ts | 18 +++++++++ .../investigate_in_timeline_action.test.tsx | 40 +++++++++---------- .../use_investigate_in_timeline.test.tsx | 40 +++++++++---------- .../use_investigate_in_timeline.tsx | 5 +++ .../components/fields_browser/index.tsx | 18 ++++++++- .../components/open_timeline/index.tsx | 13 +++++- .../timeline/body/actions/index.tsx | 25 +++++++++++- .../timeline/header/title_and_description.tsx | 10 ++++- .../timelines/public/container/index.tsx | 13 +++--- .../public/hooks/use_bulk_action_items.tsx | 12 ++++++ .../timelines/public/lib/apm/constants.ts | 12 ++++++ .../plugins/timelines/public/lib/apm/types.ts | 15 +++++++ .../public/lib/apm/use_start_transaction.ts | 36 +++++++++++++++++ 13 files changed, 202 insertions(+), 55 deletions(-) create mode 100644 x-pack/plugins/timelines/public/lib/apm/constants.ts create mode 100644 x-pack/plugins/timelines/public/lib/apm/types.ts create mode 100644 x-pack/plugins/timelines/public/lib/apm/use_start_transaction.ts diff --git a/x-pack/plugins/security_solution/public/common/lib/apm/user_actions.ts b/x-pack/plugins/security_solution/public/common/lib/apm/user_actions.ts index ba2a3fa77e637d..44703b4f5707cb 100644 --- a/x-pack/plugins/security_solution/public/common/lib/apm/user_actions.ts +++ b/x-pack/plugins/security_solution/public/common/lib/apm/user_actions.ts @@ -33,3 +33,21 @@ export const RULES_TABLE_ACTIONS = { PREVIEW_ON: `${APP_UI_ID} rulesTable technicalPreview on`, PREVIEW_OFF: `${APP_UI_ID} rulesTable technicalPreview off`, }; + +export const TIMELINE_ACTIONS = { + SAVE: `${APP_UI_ID} timeline save`, + DUPLICATE: `${APP_UI_ID} timeline duplicate`, // it includes duplicate template, create template from timeline and create timeline from template + DELETE: `${APP_UI_ID} timeline delete`, + BULK_DELETE: `${APP_UI_ID} timeline bulkDelete`, +}; + +export const ALERTS_ACTIONS = { + OPEN_ANALYZER: `${APP_UI_ID} alerts openAnalyzer`, + OPEN_SESSION_VIEW: `${APP_UI_ID} alerts openSessionView`, + INVESTIGATE_IN_TIMELINE: `${APP_UI_ID} alerts investigateInTimeline`, +}; + +export const FIELD_BROWSER_ACTIONS = { + FIELD_SAVED: `${APP_UI_ID} fieldBrowser fieldSaved`, + FIELD_DELETED: `${APP_UI_ID} fieldBrowser fieldDeleted`, +}; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx index 5eebdd18acfd4b..f4b581060e1ef7 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_timeline_action.test.tsx @@ -11,7 +11,6 @@ import { KibanaServices, useKibana } from '../../../../common/lib/kibana'; import type { Ecs } from '../../../../../common/ecs'; import * as actions from '../actions'; import { coreMock } from '@kbn/core/public/mocks'; -import type { SendAlertToTimelineActionProps } from '../types'; import { InvestigateInTimelineAction } from './investigate_in_timeline_action'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; @@ -30,9 +29,26 @@ const ecsRowData: Ecs = { }; jest.mock('../../../../common/lib/kibana'); +jest.mock('../../../../common/lib/apm/use_start_transaction'); jest.mock('../../../../common/hooks/use_app_toasts'); jest.mock('../actions'); +(KibanaServices.get as jest.Mock).mockReturnValue(coreMock.createStart()); +const mockSendAlertToTimeline = jest.spyOn(actions, 'sendAlertToTimelineAction'); +(useKibana as jest.Mock).mockReturnValue({ + services: { + data: { + search: { + searchStrategyClient: jest.fn(), + }, + query: jest.fn(), + }, + }, +}); +(useAppToasts as jest.Mock).mockReturnValue({ + addError: jest.fn(), +}); + const props = { ecsRowData, onInvestigateInTimelineAlertClick: () => {}, @@ -40,28 +56,8 @@ const props = { }; describe('use investigate in timeline hook', () => { - let mockSendAlertToTimeline: jest.SpyInstance, [SendAlertToTimelineActionProps]>; - - beforeEach(() => { - const coreStartMock = coreMock.createStart(); - (KibanaServices.get as jest.Mock).mockReturnValue(coreStartMock); - mockSendAlertToTimeline = jest.spyOn(actions, 'sendAlertToTimelineAction'); - (useKibana as jest.Mock).mockReturnValue({ - services: { - data: { - search: { - searchStrategyClient: jest.fn(), - }, - query: jest.fn(), - }, - }, - }); - (useAppToasts as jest.Mock).mockReturnValue({ - addError: jest.fn(), - }); - }); afterEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }); test('it creates a component and click handler', () => { const wrapper = render( diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx index 4fd5ebc48e49b4..eaef9169925ae2 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.test.tsx @@ -12,7 +12,6 @@ import type { Ecs } from '../../../../../common/ecs'; import { useInvestigateInTimeline } from './use_investigate_in_timeline'; import * as actions from '../actions'; import { coreMock } from '@kbn/core/public/mocks'; -import type { SendAlertToTimelineActionProps } from '../types'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; const ecsRowData: Ecs = { @@ -30,37 +29,34 @@ const ecsRowData: Ecs = { }; jest.mock('../../../../common/lib/kibana'); +jest.mock('../../../../common/lib/apm/use_start_transaction'); jest.mock('../../../../common/hooks/use_app_toasts'); jest.mock('../actions'); +(KibanaServices.get as jest.Mock).mockReturnValue(coreMock.createStart()); +const mockSendAlertToTimeline = jest.spyOn(actions, 'sendAlertToTimelineAction'); +(useKibana as jest.Mock).mockReturnValue({ + services: { + data: { + search: { + searchStrategyClient: jest.fn(), + }, + query: jest.fn(), + }, + }, +}); +(useAppToasts as jest.Mock).mockReturnValue({ + addError: jest.fn(), +}); + const props = { ecsRowData, onInvestigateInTimelineAlertClick: () => {}, }; describe('use investigate in timeline hook', () => { - let mockSendAlertToTimeline: jest.SpyInstance, [SendAlertToTimelineActionProps]>; - - beforeEach(() => { - const coreStartMock = coreMock.createStart(); - (KibanaServices.get as jest.Mock).mockReturnValue(coreStartMock); - mockSendAlertToTimeline = jest.spyOn(actions, 'sendAlertToTimelineAction'); - (useKibana as jest.Mock).mockReturnValue({ - services: { - data: { - search: { - searchStrategyClient: jest.fn(), - }, - query: jest.fn(), - }, - }, - }); - (useAppToasts as jest.Mock).mockReturnValue({ - addError: jest.fn(), - }); - }); afterEach(() => { - jest.resetAllMocks(); + jest.clearAllMocks(); }); test('it creates a component and click handler', () => { const { result } = renderHook(() => useInvestigateInTimeline(props), { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx index ce5b7ee9c5de53..8d5eb34fe580ff 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_investigate_in_timeline.tsx @@ -30,6 +30,8 @@ import { ACTION_INVESTIGATE_IN_TIMELINE } from '../translations'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; import { getField } from '../../../../helpers'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; +import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; +import { ALERTS_ACTIONS } from '../../../../common/lib/apm/user_actions'; interface UseInvestigateInTimelineActionProps { ecsRowData?: Ecs | Ecs[] | null; @@ -45,6 +47,7 @@ export const useInvestigateInTimeline = ({ data: { search: searchStrategyClient, query }, } = useKibana().services; const dispatch = useDispatch(); + const { startTransaction } = useStartTransaction(); const { services } = useKibana(); const { getExceptionListsItems } = useApi(services.http); @@ -141,6 +144,7 @@ export const useInvestigateInTimeline = ({ ); const investigateInTimelineAlertClick = useCallback(async () => { + startTransaction({ name: ALERTS_ACTIONS.INVESTIGATE_IN_TIMELINE }); if (onInvestigateInTimelineAlertClick) { onInvestigateInTimelineAlertClick(); } @@ -154,6 +158,7 @@ export const useInvestigateInTimeline = ({ }); } }, [ + startTransaction, createTimeline, ecsRowData, onInvestigateInTimelineAlertClick, diff --git a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx index 0d7a23800d4049..d15fd7a501ea09 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx @@ -24,6 +24,8 @@ import { defaultColumnHeaderType } from '../timeline/body/column_headers/default import { DEFAULT_COLUMN_MIN_WIDTH } from '../timeline/body/constants'; import { useCreateFieldButton } from './create_field_button'; import { useFieldTableColumns } from './field_table_columns'; +import { useStartTransaction } from '../../../common/lib/apm/use_start_transaction'; +import { FIELD_BROWSER_ACTIONS } from '../../../common/lib/apm/user_actions'; export type FieldEditorActions = { closeEditor: () => void } | null; export type FieldEditorActionsRef = MutableRefObject; @@ -50,6 +52,7 @@ export const useFieldBrowserOptions: UseFieldBrowserOptions = ({ const dispatch = useDispatch(); const [dataView, setDataView] = useState(null); + const { startTransaction } = useStartTransaction(); const { indexFieldsSearch } = useDataView(); const { dataViewFieldEditor, @@ -75,6 +78,8 @@ export const useFieldBrowserOptions: UseFieldBrowserOptions = ({ ctx: { dataView }, fieldName, onSave: async (savedField: DataViewField) => { + startTransaction({ name: FIELD_BROWSER_ACTIONS.FIELD_SAVED }); + // Fetch the updated list of fields // Using cleanCache since the number of fields might have not changed, but we need to update the state anyway await indexFieldsSearch({ dataViewId: selectedDataViewId, cleanCache: true }); @@ -124,6 +129,7 @@ export const useFieldBrowserOptions: UseFieldBrowserOptions = ({ indexFieldsSearch, dispatch, timelineId, + startTransaction, ] ); @@ -134,6 +140,8 @@ export const useFieldBrowserOptions: UseFieldBrowserOptions = ({ ctx: { dataView }, fieldName, onDelete: async () => { + startTransaction({ name: FIELD_BROWSER_ACTIONS.FIELD_DELETED }); + // Fetch the updated list of fields await indexFieldsSearch({ dataViewId: selectedDataViewId }); @@ -147,7 +155,15 @@ export const useFieldBrowserOptions: UseFieldBrowserOptions = ({ }); } }, - [dataView, selectedDataViewId, dataViewFieldEditor, indexFieldsSearch, dispatch, timelineId] + [ + dataView, + selectedDataViewId, + dataViewFieldEditor, + indexFieldsSearch, + dispatch, + timelineId, + startTransaction, + ] ); const hasFieldEditPermission = useMemo( diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx index 1dd795bd795b59..628d2bf14d5e53 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.tsx @@ -48,6 +48,8 @@ import { deleteTimelinesByIds } from '../../containers/api'; import type { Direction } from '../../../../common/search_strategy'; import { SourcererScopeName } from '../../../common/store/sourcerer/model'; import { useSourcererDataView } from '../../../common/containers/sourcerer'; +import { useStartTransaction } from '../../../common/lib/apm/use_start_transaction'; +import { TIMELINE_ACTIONS } from '../../../common/lib/apm/user_actions'; interface OwnProps { /** Displays open timeline in modal */ @@ -86,6 +88,7 @@ export const StatefulOpenTimelineComponent = React.memo( title, }) => { const dispatch = useDispatch(); + const { startTransaction } = useStartTransaction(); /** Required by EuiTable for expandable rows: a map of `TimelineResult.savedObjectId` to rendered notes */ const [itemIdToExpandedNotesRowMap, setItemIdToExpandedNotesRowMap] = useState< Record @@ -197,6 +200,10 @@ export const StatefulOpenTimelineComponent = React.memo( const deleteTimelines: DeleteTimelines = useCallback( async (timelineIds: string[]) => { + startTransaction({ + name: timelineIds.length > 1 ? TIMELINE_ACTIONS.BULK_DELETE : TIMELINE_ACTIONS.DELETE, + }); + if (timelineIds.includes(timelineSavedObjectId)) { dispatch( dispatchCreateNewTimeline({ @@ -212,7 +219,7 @@ export const StatefulOpenTimelineComponent = React.memo( await deleteTimelinesByIds(timelineIds); refetch(); }, - [timelineSavedObjectId, refetch, dispatch, dataViewId, selectedPatterns] + [startTransaction, timelineSavedObjectId, refetch, dispatch, dataViewId, selectedPatterns] ); const onDeleteOneTimeline: OnDeleteOneTimeline = useCallback( @@ -274,6 +281,10 @@ export const StatefulOpenTimelineComponent = React.memo( const openTimeline: OnOpenTimeline = useCallback( ({ duplicate, timelineId, timelineType: timelineTypeToOpen }) => { + if (duplicate) { + startTransaction({ name: TIMELINE_ACTIONS.DUPLICATE }); + } + if (isModal && closeModalTimeline != null) { closeModalTimeline(); } diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx index 1e53ba23c39af3..ea7d6e0ef46876 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx @@ -39,6 +39,8 @@ import { TimelineId, TimelineTabs } from '../../../../../../common/types/timelin import { timelineActions, timelineSelectors } from '../../../../store/timeline'; import { timelineDefaults } from '../../../../store/timeline/defaults'; import { isInvestigateInResolverActionEnabled } from '../../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver'; +import { useStartTransaction } from '../../../../../common/lib/apm/use_start_transaction'; +import { ALERTS_ACTIONS } from '../../../../../common/lib/apm/user_actions'; export const isAlert = (eventType: TimelineEventsType | Omit): boolean => eventType === 'signal'; @@ -71,6 +73,7 @@ const ActionsComponent: React.FC = ({ const tGridEnabled = useIsExperimentalFeatureEnabled('tGridEnabled'); const emptyNotes: string[] = []; const getTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []); + const { startTransaction } = useStartTransaction(); const onPinEvent: OnPinEvent = useCallback( (evtId) => dispatch(timelineActions.pinEvent({ id: timelineId, eventId: evtId })), @@ -118,6 +121,8 @@ const ActionsComponent: React.FC = ({ const { setGlobalFullScreen } = useGlobalFullScreen(); const { setTimelineFullScreen } = useTimelineFullScreen(); const handleClick = useCallback(() => { + startTransaction({ name: ALERTS_ACTIONS.OPEN_ANALYZER }); + const dataGridIsFullScreen = document.querySelector('.euiDataGrid--fullScreen'); dispatch(updateTimelineGraphEventId({ id: timelineId, graphEventId: ecsData._id })); if (timelineId === TimelineId.active) { @@ -130,7 +135,14 @@ const ActionsComponent: React.FC = ({ setGlobalFullScreen(true); } } - }, [dispatch, ecsData._id, timelineId, setGlobalFullScreen, setTimelineFullScreen]); + }, [ + startTransaction, + dispatch, + timelineId, + ecsData._id, + setTimelineFullScreen, + setGlobalFullScreen, + ]); const sessionViewConfig = useMemo(() => { const { process, _id, timestamp } = ecsData; @@ -155,6 +167,8 @@ const ActionsComponent: React.FC = ({ const openSessionView = useCallback(() => { const dataGridIsFullScreen = document.querySelector('.euiDataGrid--fullScreen'); + startTransaction({ name: ALERTS_ACTIONS.OPEN_SESSION_VIEW }); + if (timelineId === TimelineId.active) { if (dataGridIsFullScreen) { setTimelineFullScreen(true); @@ -170,7 +184,14 @@ const ActionsComponent: React.FC = ({ if (sessionViewConfig !== null) { dispatch(updateTimelineSessionViewConfig({ id: timelineId, sessionViewConfig })); } - }, [dispatch, timelineId, sessionViewConfig, setGlobalFullScreen, setTimelineFullScreen]); + }, [ + startTransaction, + timelineId, + sessionViewConfig, + setTimelineFullScreen, + dispatch, + setGlobalFullScreen, + ]); return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/header/title_and_description.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/header/title_and_description.tsx index bd267abb23c7db..d887b72cdb33a8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/header/title_and_description.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/header/title_and_description.tsx @@ -30,6 +30,8 @@ import { useCreateTimeline } from '../properties/use_create_timeline'; import * as commonI18n from '../properties/translations'; import * as i18n from './translations'; import { formSchema } from './schema'; +import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; +import { TIMELINE_ACTIONS } from '../../../../common/lib/apm/user_actions'; const CommonUseField = getUseField({ component: Field }); interface TimelineTitleAndDescriptionProps { @@ -44,6 +46,7 @@ interface TimelineTitleAndDescriptionProps { // the unsaved timeline / template export const TimelineTitleAndDescription = React.memo( ({ closeSaveTimeline, initialFocus, timelineId, showWarning }) => { + const { startTransaction } = useStartTransaction(); const getTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []); const { isSaving, @@ -99,6 +102,11 @@ export const TimelineTitleAndDescription = React.memo { + startTransaction({ name: TIMELINE_ACTIONS.SAVE }); + submit(); + }, [submit, startTransaction]); + const handleCancel = useCallback(() => { if (showWarning) { handleCreateNewTimeline(); @@ -236,7 +244,7 @@ export const TimelineTitleAndDescription = React.memo {saveButtonTitle} diff --git a/x-pack/plugins/timelines/public/container/index.tsx b/x-pack/plugins/timelines/public/container/index.tsx index ef82aa527bab3f..15e72e7aed2bba 100644 --- a/x-pack/plugins/timelines/public/container/index.tsx +++ b/x-pack/plugins/timelines/public/container/index.tsx @@ -16,7 +16,6 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; import { clearEventsLoading, clearEventsDeleted, @@ -43,7 +42,7 @@ import type { KueryFilterQueryKind } from '../../common/types/timeline'; import { useAppToasts } from '../hooks/use_app_toasts'; import { TimelineId } from '../store/t_grid/types'; import * as i18n from './translations'; -import { TimelinesStartPlugins } from '../types'; +import { getSearchTransactionName, useStartTransaction } from '../lib/apm/use_start_transaction'; export type InspectResponse = Inspect & { response: string[] }; @@ -118,14 +117,16 @@ export const initSortDefault = [ ]; const useApmTracking = (timelineId: string) => { - const { apm } = useKibana().services; + const { startTransaction } = useStartTransaction(); const startTracking = useCallback(() => { // Create the transaction, the managed flag is turned off to prevent it from being polluted by non-related automatic spans. // The managed flag can be turned on to investigate high latency requests in APM. // However, note that by enabling the managed flag, the transaction trace may be distorted by other requests information. - const transaction = apm?.startTransaction(`Timeline search ${timelineId}`, 'http-request', { - managed: false, + const transaction = startTransaction({ + name: getSearchTransactionName(timelineId), + type: 'http-request', + options: { managed: false }, }); // Create a blocking span to control the transaction time and prevent it from closing automatically with partial batch responses. // The blocking span needs to be ended manually when the batched request finishes. @@ -136,7 +137,7 @@ const useApmTracking = (timelineId: string) => { span?.end(); }, }; - }, [apm, timelineId]); + }, [startTransaction, timelineId]); return { startTracking }; }; diff --git a/x-pack/plugins/timelines/public/hooks/use_bulk_action_items.tsx b/x-pack/plugins/timelines/public/hooks/use_bulk_action_items.tsx index 02abe3a229df41..202a648916081e 100644 --- a/x-pack/plugins/timelines/public/hooks/use_bulk_action_items.tsx +++ b/x-pack/plugins/timelines/public/hooks/use_bulk_action_items.tsx @@ -13,6 +13,8 @@ import type { AlertStatus, BulkActionsProps } from '../../common/types/timeline' import { useUpdateAlertsStatus } from '../container/use_update_alerts'; import { useAppToasts } from './use_app_toasts'; import { STANDALONE_ID } from '../components/t_grid/standalone'; +import { useStartTransaction } from '../lib/apm/use_start_transaction'; +import { APM_USER_INTERACTIONS } from '../lib/apm/constants'; export const getUpdateAlertsQuery = (eventIds: Readonly) => { return { bool: { filter: { terms: { _id: eventIds } } } }; @@ -33,6 +35,7 @@ export const useBulkActionItems = ({ }: BulkActionsProps) => { const { updateAlertStatus } = useUpdateAlertsStatus(timelineId !== STANDALONE_ID); const { addSuccess, addError, addWarning } = useAppToasts(); + const { startTransaction } = useStartTransaction(); const onAlertStatusUpdateSuccess = useCallback( (updated: number, conflicts: number, newStatus: AlertStatus) => { @@ -88,6 +91,14 @@ export const useBulkActionItems = ({ const onClickUpdate = useCallback( async (status: AlertStatus) => { + if (query) { + startTransaction({ name: APM_USER_INTERACTIONS.BULK_QUERY_STATUS_UPDATE }); + } else if (eventIds.length > 1) { + startTransaction({ name: APM_USER_INTERACTIONS.BULK_STATUS_UPDATE }); + } else { + startTransaction({ name: APM_USER_INTERACTIONS.STATUS_UPDATE }); + } + try { setEventsLoading({ eventIds, isLoading: true }); @@ -120,6 +131,7 @@ export const useBulkActionItems = ({ setEventsDeleted, onAlertStatusUpdateSuccess, onAlertStatusUpdateFailure, + startTransaction, ] ); diff --git a/x-pack/plugins/timelines/public/lib/apm/constants.ts b/x-pack/plugins/timelines/public/lib/apm/constants.ts new file mode 100644 index 00000000000000..6b8036f2d2393a --- /dev/null +++ b/x-pack/plugins/timelines/public/lib/apm/constants.ts @@ -0,0 +1,12 @@ +/* + * 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 const APM_USER_INTERACTIONS = { + BULK_QUERY_STATUS_UPDATE: 'Timeline bulkQueryStatusUpdate', + BULK_STATUS_UPDATE: 'Timeline bulkStatusUpdate', + STATUS_UPDATE: 'Timeline statusUpdate', +} as const; diff --git a/x-pack/plugins/timelines/public/lib/apm/types.ts b/x-pack/plugins/timelines/public/lib/apm/types.ts new file mode 100644 index 00000000000000..eb52ab17b2f94b --- /dev/null +++ b/x-pack/plugins/timelines/public/lib/apm/types.ts @@ -0,0 +1,15 @@ +/* + * 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 { APM_USER_INTERACTIONS } from './constants'; + +export type ApmUserInteractionName = + typeof APM_USER_INTERACTIONS[keyof typeof APM_USER_INTERACTIONS]; + +export type ApmSearchRequestName = `Timeline search ${string}`; + +export type ApmTransactionName = ApmSearchRequestName | ApmUserInteractionName; diff --git a/x-pack/plugins/timelines/public/lib/apm/use_start_transaction.ts b/x-pack/plugins/timelines/public/lib/apm/use_start_transaction.ts new file mode 100644 index 00000000000000..fa47db412e467f --- /dev/null +++ b/x-pack/plugins/timelines/public/lib/apm/use_start_transaction.ts @@ -0,0 +1,36 @@ +/* + * 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 { useCallback } from 'react'; +import type { TransactionOptions } from '@elastic/apm-rum'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { TimelinesStartPlugins } from '../../types'; +import type { ApmSearchRequestName, ApmTransactionName } from './types'; + +const DEFAULT_TRANSACTION_OPTIONS: TransactionOptions = { managed: true }; + +interface StartTransactionOptions { + name: ApmTransactionName; + type?: string; + options?: TransactionOptions; +} + +export const useStartTransaction = () => { + const { apm } = useKibana().services; + + const startTransaction = useCallback( + ({ name, type = 'user-interaction', options }: StartTransactionOptions) => { + return apm?.startTransaction(name, type, options ?? DEFAULT_TRANSACTION_OPTIONS); + }, + [apm] + ); + + return { startTransaction }; +}; + +export const getSearchTransactionName = (timelineId: string): ApmSearchRequestName => + `Timeline search ${timelineId}`; From 7360c1dc78901ad6de2559cb3b1c36023fae8e9b Mon Sep 17 00:00:00 2001 From: Luke Gmys Date: Fri, 9 Sep 2022 13:11:02 +0200 Subject: [PATCH 002/144] [TIP] Fix flyout flash on filter change / table refresh (#140301) --- .../indicators_table/indicators_table.tsx | 99 +++++++++++-------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx index eea9acaabda31e..9cd711d313a542 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx @@ -82,18 +82,6 @@ export const IndicatorsTable: VFC = ({ const start = pagination.pageIndex * pagination.pageSize; const end = start + pagination.pageSize; - const flyoutFragment = useMemo( - () => - expanded ? ( - setExpanded(undefined)} - /> - ) : null, - [expanded, fieldTypesMap] - ); - const leadingControlColumns = useMemo( () => [ { @@ -140,42 +128,71 @@ export const IndicatorsTable: VFC = ({ onToggleColumn: handleToggleColumn, }); - if (loading) { + const flyoutFragment = useMemo( + () => + expanded ? ( + setExpanded(undefined)} + /> + ) : null, + [expanded, fieldTypesMap] + ); + + const gridFragment = useMemo(() => { + if (loading) { + return ( + + + + + + + + ); + } + + if (!indicatorCount) { + return ; + } + return ( - - - - - - - + ); - } - - if (!indicatorCount) { - return ; - } + }, [ + columnVisibility, + columns, + indicatorCount, + leadingControlColumns, + loading, + onChangeItemsPerPage, + onChangePage, + pagination, + renderCellValue, + toolbarOptions, + ]); return (
- {flyoutFragment} + {gridFragment}
); From c182d3226fecdd38f28b22467985f08cee7fca90 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Fri, 9 Sep 2022 13:47:47 +0200 Subject: [PATCH 003/144] [Enterprise Search] Modify licensing callout for 8.5 (#140374) --- .../new_index/licensing_callout.tsx | 131 +++++---- .../method_connector/method_connector.tsx | 269 ++++++++++-------- .../method_crawler/method_crawler.tsx | 9 +- .../new_index/new_search_index_template.tsx | 12 +- 4 files changed, 244 insertions(+), 177 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/licensing_callout.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/licensing_callout.tsx index ec514dfc5b5b12..8325b1a5305ee1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/licensing_callout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/licensing_callout.tsx @@ -9,59 +9,90 @@ import React from 'react'; import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; import { docLinks } from '../../../shared/doc_links/doc_links'; -export const LicensingCallout: React.FC = () => ( - -

- {i18n.translate('xpack.enterpriseSearch.content.licensingCallout.contentOne', { +export enum LICENSING_FEATURE { + NATIVE_CONNECTOR = 'nativeConnector', + CRAWLER = 'crawler', + INFERENCE = 'inference', +} + +type ContentBlock = Record; + +export const LicensingCallout: React.FC<{ feature: LICENSING_FEATURE }> = ({ feature }) => { + const firstContentBlock: ContentBlock = { + [LICENSING_FEATURE.NATIVE_CONNECTOR]: i18n.translate( + 'xpack.enterpriseSearch.content.licensingCallout.nativeConnector.contentOne', + { defaultMessage: - 'This feature requires a Platinum license or higher. From 8.5 this feature will be unavailable to Standard license self-managed deployments.', - })} -

-

- - - - ), - }} - /> -

-

- {i18n.translate('xpack.enterpriseSearch.content.licensingCallout.contentThree', { + 'Built-in connectors require a Platinum license or higher and are not available to Standard license self-managed deployments. You need to upgrade to use this feature.', + } + ), + [LICENSING_FEATURE.CRAWLER]: i18n.translate( + 'xpack.enterpriseSearch.content.licensingCallout.crawler.contentOne', + { defaultMessage: - "Did you know that the web crawler is available with a Standard Elastic Cloud license? Elastic Cloud gives you the flexibility to run where you want. Deploy our managed service on Google Cloud, Microsoft Azure, or Amazon Web Services, and we'll handle the maintenance and upkeep for you.", + 'The web crawler requires a Platinum license or higher and is not available to Standard license self-managed deployments. You need to upgrade to use this feature.', + } + ), + [LICENSING_FEATURE.INFERENCE]: i18n.translate( + 'xpack.enterpriseSearch.content.licensingCallout.inference.contentOne', + { + defaultMessage: + 'Inference processors require a Platinum license or higher and are not available to Standard license self-managed deployments. You need to upgrade to use this feature.', + } + ), + }; + + const secondContentBlock: ContentBlock = { + [LICENSING_FEATURE.NATIVE_CONNECTOR]: i18n.translate( + 'xpack.enterpriseSearch.content.licensingCallout.contentTwo', + { + defaultMessage: + "Did you know that built-in connectors are available with a Standard Elastic Cloud license? Elastic Cloud gives you the flexibility to run where you want. Deploy our managed service on Google Cloud, Microsoft Azure, or Amazon Web Services, and we'll handle the maintenance and upkeep for you.", + } + ), + [LICENSING_FEATURE.CRAWLER]: i18n.translate( + 'xpack.enterpriseSearch.content.licensingCallout.crawler.contentTwo', + { + defaultMessage: + "Did you know that web crawlers are available with a Standard Elastic Cloud license? Elastic Cloud gives you the flexibility to run where you want. Deploy our managed service on Google Cloud, Microsoft Azure, or Amazon Web Services, and we'll handle the maintenance and upkeep for you.", + } + ), + [LICENSING_FEATURE.INFERENCE]: i18n.translate( + 'xpack.enterpriseSearch.content.licensingCallout.inference.contentTwo', + { + defaultMessage: + "Did you know that inference processors are available with a Standard Elastic Cloud license? Elastic Cloud gives you the flexibility to run where you want. Deploy our managed service on Google Cloud, Microsoft Azure, or Amazon Web Services, and we'll handle the maintenance and upkeep for you.", + } + ), + }; + + return ( + - - - - {i18n.translate('xpack.enterpriseSearch.workplaceSearch.explorePlatinumFeatures.link', { - defaultMessage: 'Explore Platinum features', - })} - - - - - {i18n.translate('xpack.enterpriseSearch.content.licensingCallout.contentCloudTrial', { - defaultMessage: 'Sign up for a free 14-day Elastic Cloud trial.', - })} - - - - -); + > +

{firstContentBlock[feature]}

+

{secondContentBlock[feature]}

+ + + + {i18n.translate('xpack.enterpriseSearch.workplaceSearch.explorePlatinumFeatures.link', { + defaultMessage: 'Explore Platinum features', + })} + + + + + {i18n.translate('xpack.enterpriseSearch.content.licensingCallout.contentCloudTrial', { + defaultMessage: 'Sign up for a free 14-day Elastic Cloud trial.', + })} + + + +
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx index fe62dd439e3a3b..70cf83fbb97645 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_connector/method_connector.tsx @@ -9,7 +9,14 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { EuiConfirmModal, EuiLink, EuiSteps, EuiText } from '@elastic/eui'; +import { + EuiConfirmModal, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiSteps, + EuiText, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -17,8 +24,11 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { Status } from '../../../../../../common/types/api'; import { docLinks } from '../../../../shared/doc_links'; +import { KibanaLogic } from '../../../../shared/kibana'; +import { LicensingLogic } from '../../../../shared/licensing'; import { AddConnectorApiLogic } from '../../../api/connector/add_connector_api_logic'; +import { LicensingCallout, LICENSING_FEATURE } from '../licensing_callout'; import { CREATE_ELASTICSEARCH_INDEX_STEP, BUILD_SEARCH_EXPERIENCE_STEP } from '../method_steps'; import { NewSearchIndexLogic } from '../new_search_index_logic'; import { NewSearchIndexTemplate } from '../new_search_index_template'; @@ -33,134 +43,151 @@ export const MethodConnector: React.FC<{ isNative: boolean }> = ({ isNative }) = const { isModalVisible } = useValues(AddConnectorLogic); const { setIsModalVisible } = useActions(AddConnectorLogic); const { fullIndexName, language } = useValues(NewSearchIndexLogic); + const { isCloud } = useValues(KibanaLogic); + const { hasPlatinumLicense } = useValues(LicensingLogic); + + const isGated = isNative && !isCloud && !hasPlatinumLicense; return ( - { - apiReset(); - }} - onSubmit={(name, lang) => makeRequest({ indexName: name, isNative, language: lang })} - buttonLoading={status === Status.LOADING} - > - -

- -

- - ), - status: 'incomplete', - title: i18n.translate( - 'xpack.enterpriseSearch.content.newIndex.methodConnector.steps.nativeConnector.title', - { - defaultMessage: 'Use a pre-built connector to populate your index', - } - ), - titleSize: 'xs', - } - : { - children: isNative ? ( - -

- -

-
- ) : ( - -

- - {i18n.translate( - 'xpack.enterpriseSearch.content.newIndex.methodConnector.steps.buildConnector.bulkAPILink', - { defaultMessage: 'Bulk API' } - )} - - ), - }} - /> -

-
- ), - status: 'incomplete', - title: i18n.translate( - 'xpack.enterpriseSearch.content.newIndex.methodConnector.steps.buildConnector.title', - { - defaultMessage: 'Build and configure a connector', - } - ), - titleSize: 'xs', - }, - BUILD_SEARCH_EXPERIENCE_STEP, - ]} - /> - {isModalVisible && ( - + {isGated && ( + + + + )} + + { - event?.preventDefault(); - setIsModalVisible(false); + type="connector" + onNameChange={() => { + apiReset(); }} - onConfirm={(event) => { - event.preventDefault(); - makeRequest({ - deleteExistingConnector: true, - indexName: fullIndexName, - isNative, - language, - }); - }} - cancelButtonText={i18n.translate( - 'xpack.enterpriseSearch.content.newIndex.steps.buildConnector.confirmModal.cancelButton.label', - { - defaultMessage: 'Cancel', - } - )} - confirmButtonText={i18n.translate( - 'xpack.enterpriseSearch.content.newIndex.steps.buildConnector.confirmModal.confirmButton.label', - { - defaultMessage: 'Replace configuration', - } - )} - defaultFocusedButton="confirm" + onSubmit={(name, lang) => makeRequest({ indexName: name, isNative, language: lang })} + buttonLoading={status === Status.LOADING} > - {i18n.translate( - 'xpack.enterpriseSearch.content.newIndex.steps.buildConnector.confirmModal.description', - { - defaultMessage: - 'A deleted index named {indexName} was originally tied to an existing connector configuration. Would you like to replace the existing connector configuration with a new one?', - values: { - indexName: fullIndexName, - }, - } + +

+ +

+ + ), + status: 'incomplete', + title: i18n.translate( + 'xpack.enterpriseSearch.content.newIndex.methodConnector.steps.nativeConnector.title', + { + defaultMessage: 'Use a pre-built connector to populate your index', + } + ), + titleSize: 'xs', + } + : { + children: isNative ? ( + +

+ +

+
+ ) : ( + +

+ + {i18n.translate( + 'xpack.enterpriseSearch.content.newIndex.methodConnector.steps.buildConnector.bulkAPILink', + { defaultMessage: 'Bulk API' } + )} + + ), + }} + /> +

+
+ ), + status: 'incomplete', + title: i18n.translate( + 'xpack.enterpriseSearch.content.newIndex.methodConnector.steps.buildConnector.title', + { + defaultMessage: 'Build and configure a connector', + } + ), + titleSize: 'xs', + }, + BUILD_SEARCH_EXPERIENCE_STEP, + ]} + /> + {isModalVisible && ( + { + event?.preventDefault(); + setIsModalVisible(false); + }} + onConfirm={(event) => { + event.preventDefault(); + makeRequest({ + deleteExistingConnector: true, + indexName: fullIndexName, + isNative, + language, + }); + }} + cancelButtonText={i18n.translate( + 'xpack.enterpriseSearch.content.newIndex.steps.buildConnector.confirmModal.cancelButton.label', + { + defaultMessage: 'Cancel', + } + )} + confirmButtonText={i18n.translate( + 'xpack.enterpriseSearch.content.newIndex.steps.buildConnector.confirmModal.confirmButton.label', + { + defaultMessage: 'Replace configuration', + } + )} + defaultFocusedButton="confirm" + > + {i18n.translate( + 'xpack.enterpriseSearch.content.newIndex.steps.buildConnector.confirmModal.description', + { + defaultMessage: + 'A deleted index named {indexName} was originally tied to an existing connector configuration. Would you like to replace the existing connector configuration with a new one?', + values: { + indexName: fullIndexName, + }, + } + )} + )} -
- )} -
+ + + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler.tsx index 296911022ee906..b96afab404e68f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/method_crawler/method_crawler.tsx @@ -18,7 +18,7 @@ import { docLinks } from '../../../../shared/doc_links'; import { KibanaLogic } from '../../../../shared/kibana'; import { LicensingLogic } from '../../../../shared/licensing'; import { CreateCrawlerIndexApiLogic } from '../../../api/crawler/create_crawler_index_api_logic'; -import { LicensingCallout } from '../licensing_callout'; +import { LicensingCallout, LICENSING_FEATURE } from '../licensing_callout'; import { CREATE_ELASTICSEARCH_INDEX_STEP, BUILD_SEARCH_EXPERIENCE_STEP } from '../method_steps'; import { NewSearchIndexTemplate } from '../new_search_index_template'; @@ -30,13 +30,15 @@ export const MethodCrawler: React.FC = () => { const { isCloud } = useValues(KibanaLogic); const { hasPlatinumLicense } = useValues(LicensingLogic); + const isGated = !isCloud && !hasPlatinumLicense; + MethodCrawlerLogic.mount(); return ( - {!isCloud && !hasPlatinumLicense && ( + {isGated && ( - + )} @@ -49,6 +51,7 @@ export const MethodCrawler: React.FC = () => { )} type="crawler" onSubmit={(indexName, language) => makeRequest({ indexName, language })} + disabled={isGated} buttonLoading={status === Status.LOADING} docsUrl={docLinks.crawlerOverview} > diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx index 69baaee26488fa..6401db2a7974df 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/new_search_index_template.tsx @@ -32,6 +32,7 @@ import { LanguageForOptimization } from './types'; export interface Props { buttonLoading?: boolean; + disabled?: boolean; docsUrl?: string; error?: string | React.ReactNode; onNameChange?(name: string): void; @@ -42,6 +43,7 @@ export interface Props { export const NewSearchIndexTemplate: React.FC = ({ children, + disabled, docsUrl, error, title, @@ -101,12 +103,12 @@ export const NewSearchIndexTemplate: React.FC = ({ return ( { event.preventDefault(); onSubmit(fullIndexName, language); }} - component="form" - id="enterprise-search-add-connector" > @@ -118,6 +120,7 @@ export const NewSearchIndexTemplate: React.FC = ({ = ({ } )} fullWidth + disabled={disabled} isInvalid={false} value={rawName} onChange={handleNameChange} @@ -164,6 +168,7 @@ export const NewSearchIndexTemplate: React.FC = ({ = ({ )} > = ({ From 46a476275c4d60c8f8a9d2eabef0156d55e5e157 Mon Sep 17 00:00:00 2001 From: doakalexi <109488926+doakalexi@users.noreply.github.com> Date: Fri, 9 Sep 2022 08:01:35 -0400 Subject: [PATCH 004/144] Removing tests (#140127) --- .../server/task_runner/task_runner.test.ts | 227 +----------------- 1 file changed, 2 insertions(+), 225 deletions(-) diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts index a90c274ce2e867..4ce85f54c3dc52 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.test.ts @@ -6,7 +6,6 @@ */ import sinon from 'sinon'; -import { schema } from '@kbn/config-schema'; import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; import { RuleExecutorOptions, @@ -1447,105 +1446,6 @@ describe('Task Runner', () => { expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); }); - test('validates params before running the rule type', async () => { - const taskRunner = new TaskRunner( - { - ...ruleType, - validate: { - params: schema.object({ - param1: schema.string(), - }), - }, - }, - { - ...mockedTaskInstance, - params: { - ...mockedTaskInstance.params, - spaceId: 'foo', - }, - }, - taskRunnerFactoryInitializerParams, - inMemoryMetrics - ); - expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); - const runnerResult = await taskRunner.run(); - expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0 })); - const loggerCall = logger.error.mock.calls[0][0]; - const loggerMeta = logger.error.mock.calls[0][1]; - const loggerCallPrefix = (loggerCall as string).split('-'); - expect(loggerCallPrefix[0].trim()).toMatchInlineSnapshot( - `"Executing Rule foo:test:1 has resulted in Error: params invalid: [param1]: expected value of type [string] but got [undefined]"` - ); - expect(loggerMeta?.tags).toEqual(['test', '1', 'rule-run-failed']); - expect(loggerMeta?.error?.stack_trace).toBeDefined(); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - }); - - test('uses API key when provided', async () => { - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - taskRunnerFactoryInitializerParams, - inMemoryMetrics - ); - expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce(SAVED_OBJECT); - - await taskRunner.run(); - expect(taskRunnerFactoryInitializerParams.getRulesClientWithRequest).toHaveBeenCalledWith( - expect.objectContaining({ - headers: { - // base64 encoded "123:abc" - authorization: 'ApiKey MTIzOmFiYw==', - }, - }) - ); - const [request] = taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mock.calls[0]; - - expect(taskRunnerFactoryInitializerParams.basePathService.set).toHaveBeenCalledWith( - request, - '/' - ); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - }); - - test(`doesn't use API key when not provided`, async () => { - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - taskRunnerFactoryInitializerParams, - inMemoryMetrics - ); - expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValueOnce({ - ...SAVED_OBJECT, - attributes: { enabled: true }, - }); - - await taskRunner.run(); - - expect(taskRunnerFactoryInitializerParams.getRulesClientWithRequest).toHaveBeenCalledWith( - expect.objectContaining({ - headers: {}, - }) - ); - - const [request] = taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mock.calls[0]; - - expect(taskRunnerFactoryInitializerParams.basePathService.set).toHaveBeenCalledWith( - request, - '/' - ); - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - }); - test('rescheduled the rule if the schedule has update during a task run', async () => { const taskRunner = new TaskRunner( ruleType, @@ -1618,95 +1518,8 @@ describe('Task Runner', () => { expect(logger.error).toBeCalledTimes(1); }); - test('recovers gracefully when the Alert Task Runner throws an exception when fetching the encrypted attributes', async () => { - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockImplementation(() => { - throw new Error(GENERIC_ERROR_MESSAGE); - }); - - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - taskRunnerFactoryInitializerParams, - inMemoryMetrics - ); - expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - - const runnerResult = await taskRunner.run(); - - expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0 })); - - testAlertingEventLogCalls({ - setRuleName: false, - status: 'error', - errorReason: 'decrypt', - executionStatus: 'not-reached', - }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - }); - - test('recovers gracefully when the Alert Task Runner throws an exception when license is higher than supported', async () => { - ruleTypeRegistry.ensureRuleTypeEnabled.mockImplementation(() => { - throw new Error(GENERIC_ERROR_MESSAGE); - }); - - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - taskRunnerFactoryInitializerParams, - inMemoryMetrics - ); - expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); - - const runnerResult = await taskRunner.run(); - - expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0 })); - - testAlertingEventLogCalls({ - status: 'error', - errorReason: 'license', - executionStatus: 'not-reached', - }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - }); - - test('recovers gracefully when the Alert Task Runner throws an exception when getting internal Services', async () => { - taskRunnerFactoryInitializerParams.getRulesClientWithRequest.mockImplementation(() => { - throw new Error(GENERIC_ERROR_MESSAGE); - }); - - const taskRunner = new TaskRunner( - ruleType, - mockedTaskInstance, - taskRunnerFactoryInitializerParams, - inMemoryMetrics - ); - expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(SAVED_OBJECT); - - const runnerResult = await taskRunner.run(); - - expect(runnerResult).toEqual(generateRunnerResult({ successRatio: 0 })); - - testAlertingEventLogCalls({ - setRuleName: false, - status: 'error', - errorReason: 'unknown', - executionStatus: 'not-reached', - }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - }); - - test('recovers gracefully when the Alert Task Runner throws an exception when fetching attributes', async () => { + test('recovers gracefully when the Alert Task Runner throws an exception when loading rule to prepare for run', async () => { + // used in loadRule() which is called in prepareToRun() rulesClient.get.mockImplementation(() => { throw new Error(GENERIC_ERROR_MESSAGE); }); @@ -2381,42 +2194,6 @@ describe('Task Runner', () => { expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); }); - test('successfully bails on execution if the rule is disabled', async () => { - const state = { - ...mockedTaskInstance.state, - previousStartedAt: new Date(Date.now() - 5 * 60 * 1000).toISOString(), - }; - const taskRunner = new TaskRunner( - ruleType, - { - ...mockedTaskInstance, - state, - }, - taskRunnerFactoryInitializerParams, - inMemoryMetrics - ); - expect(AlertingEventLogger).toHaveBeenCalled(); - - rulesClient.get.mockResolvedValue(mockedRuleTypeSavedObject); - encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue({ - ...SAVED_OBJECT, - attributes: { ...SAVED_OBJECT.attributes, enabled: false }, - }); - const runnerResult = await taskRunner.run(); - expect(runnerResult.state.previousStartedAt?.toISOString()).toBe(state.previousStartedAt); - expect(runnerResult.schedule).toStrictEqual(mockedTaskInstance.schedule); - - testAlertingEventLogCalls({ - setRuleName: false, - status: 'error', - errorReason: 'disabled', - errorMessage: `Rule failed to execute because rule ran after it was disabled.`, - executionStatus: 'not-reached', - }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - }); - test('successfully stores successful runs', async () => { const taskRunner = new TaskRunner( ruleType, From 8ce4748b7efb75acc9f02069221956dc57159ed7 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Fri, 9 Sep 2022 14:03:38 +0200 Subject: [PATCH 005/144] Migrate Host risk and User risk UI to ECS schema (#140080) * Migrate Host risk and User risk indices to ECS schema * Update es_archiver to match the new calculated_level type --- .../security_solution/risk_score/all/index.ts | 41 ++- .../risk_score/common/index.ts | 5 +- .../security_solution/risk_score/kpi/index.ts | 4 +- .../security_solution/users/common/index.ts | 15 +- .../cti_details/host_risk_summary.test.tsx | 27 +- .../cti_details/host_risk_summary.tsx | 12 +- .../components/risk_score_over_time/index.tsx | 7 +- .../public/common/mock/global_state.ts | 4 +- .../host_risk_information/index.tsx | 4 +- .../host_risk_score_table/columns.tsx | 5 +- .../host_risk_score_table/index.tsx | 8 +- .../public/hosts/pages/hosts.tsx | 4 +- .../pages/navigation/host_risk_tab_body.tsx | 5 +- .../public/hosts/store/helpers.test.ts | 8 +- .../public/hosts/store/helpers.ts | 10 +- .../public/hosts/store/reducer.ts | 4 +- .../entity_analytics/header/index.test.tsx | 4 +- .../entity_analytics/header/index.tsx | 4 +- .../host_risk_score/columns.tsx | 9 +- .../host_risk_score/index.tsx | 5 +- .../user_risk_score/columns.tsx | 9 +- .../user_risk_score/index.tsx | 5 +- .../components/host_overview/index.test.tsx | 10 +- .../components/host_overview/index.tsx | 11 +- .../risky_hosts_enabled_module.test.tsx | 12 +- .../risky_hosts_enabled_module.tsx | 12 +- .../components/user_overview/index.test.tsx | 12 +- .../components/user_overview/index.tsx | 9 +- .../public/risk_score/containers/index.ts | 4 +- .../risk_score/containers/kpi/index.tsx | 29 +- .../user_risk_information/index.tsx | 4 +- .../user_risk_score_table/columns.test.tsx | 5 +- .../user_risk_score_table/columns.tsx | 5 +- .../user_risk_score_table/index.test.tsx | 15 +- .../user_risk_score_table/index.tsx | 18 +- .../pages/navigation/user_risk_tab_body.tsx | 5 +- .../public/users/pages/users.tsx | 10 +- .../public/users/store/model.ts | 4 +- .../public/users/store/reducer.ts | 2 +- .../public/users/store/selectors.ts | 2 +- .../factory/hosts/all/index.test.ts | 6 + .../factory/hosts/all/index.ts | 6 +- .../risk_score/all/query.risk_score.dsl.ts | 8 +- .../factory/risk_score/kpi/__mocks__/index.ts | 4 +- .../kpi/query.kpi_risk_score.dsl.ts | 11 +- .../translations/translations/fr-FR.json | 4 - .../translations/translations/ja-JP.json | 4 - .../translations/translations/zh-CN.json | 4 - .../es_archives/risky_hosts/data.json | 266 ++++++++--------- .../es_archives/risky_hosts/mappings.json | 56 ++-- .../es_archives/risky_users/data.json | 268 +++++++++--------- .../es_archives/risky_users/mappings.json | 58 ++-- 52 files changed, 543 insertions(+), 520 deletions(-) diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts index 2eee56f15f0834..bbb2991551f269 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/all/index.ts @@ -25,33 +25,35 @@ export interface RiskScoreRequestOptions extends IEsSearchRequest { export interface HostsRiskScoreStrategyResponse extends IEsSearchResponse { inspect?: Maybe; totalCount: number; - data: HostsRiskScore[] | undefined; + data: HostRiskScore[] | undefined; } export interface UsersRiskScoreStrategyResponse extends IEsSearchResponse { inspect?: Maybe; totalCount: number; - data: UsersRiskScore[] | undefined; + data: UserRiskScore[] | undefined; } -export interface RiskScore { - '@timestamp': string; - risk: string; - risk_stats: { - rule_risks: RuleRisk[]; - risk_score: number; - }; +export interface RiskStats { + rule_risks: RuleRisk[]; + calculated_score_norm: number; + multipliers: string[]; + calculated_level: RiskSeverity; } -export interface HostsRiskScore extends RiskScore { +export interface HostRiskScore { + '@timestamp': string; host: { name: string; + risk: RiskStats; }; } -export interface UsersRiskScore extends RiskScore { +export interface UserRiskScore { + '@timestamp': string; user: { name: string; + risk: RiskStats; }; } @@ -66,17 +68,23 @@ export type RiskScoreSortField = SortField; export const enum RiskScoreFields { timestamp = '@timestamp', hostName = 'host.name', + hostRiskScore = 'host.risk.calculated_score_norm', + hostRisk = 'host.risk.calculated_level', userName = 'user.name', - riskScore = 'risk_stats.risk_score', - risk = 'risk', + userRiskScore = 'user.risk.calculated_score_norm', + userRisk = 'user.risk.calculated_level', } export interface RiskScoreItem { _id?: Maybe; [RiskScoreFields.hostName]: Maybe; [RiskScoreFields.userName]: Maybe; - [RiskScoreFields.risk]: Maybe; - [RiskScoreFields.riskScore]: Maybe; + + [RiskScoreFields.hostRisk]: Maybe; + [RiskScoreFields.userRisk]: Maybe; + + [RiskScoreFields.hostRiskScore]: Maybe; + [RiskScoreFields.userRiskScore]: Maybe; } export const enum RiskSeverity { @@ -86,3 +94,6 @@ export const enum RiskSeverity { high = 'High', critical = 'Critical', } + +export const isUserRiskScore = (risk: HostRiskScore | UserRiskScore): risk is UserRiskScore => + 'user' in risk; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/common/index.ts index c6f651440edb93..b7ef7a4c5cbda3 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/common/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/common/index.ts @@ -33,4 +33,7 @@ export enum RiskQueries { kpiRiskScore = 'kpiRiskScore', } -export type RiskScoreAggByFields = 'host.name' | 'user.name'; +export const enum RiskScoreEntity { + host = 'host', + user = 'user', +} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/kpi/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/kpi/index.ts index 2fe24f44400881..4d95846a4f7402 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/kpi/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/risk_score/kpi/index.ts @@ -6,7 +6,7 @@ */ import type { IEsSearchRequest, IEsSearchResponse } from '@kbn/data-plugin/common'; -import type { FactoryQueryTypes, RiskScoreAggByFields, RiskSeverity } from '../..'; +import type { FactoryQueryTypes, RiskScoreEntity, RiskSeverity } from '../..'; import type { ESQuery } from '../../../../typed_json'; import type { Inspect, Maybe } from '../../../common'; @@ -15,7 +15,7 @@ export interface KpiRiskScoreRequestOptions extends IEsSearchRequest { defaultIndex: string[]; factoryQueryType?: FactoryQueryTypes; filterQuery?: ESQuery | string | undefined; - aggBy: RiskScoreAggByFields; + entity: RiskScoreEntity; } export interface KpiRiskScoreStrategyResponse extends IEsSearchResponse { diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/common/index.ts index c5cb4351757a0a..81ef6daf184a8b 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/common/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/users/common/index.ts @@ -5,22 +5,15 @@ * 2.0. */ -import type { CommonFields, Maybe, RiskSeverity, SortField } from '../../..'; +import type { CommonFields, Maybe, RiskScoreFields, RiskSeverity, SortField } from '../../..'; import type { HostEcs } from '../../../../ecs/host'; import type { UserEcs } from '../../../../ecs/user'; -export const enum UserRiskScoreFields { - timestamp = '@timestamp', - userName = 'user.name', - riskScore = 'risk_stats.risk_score', - risk = 'risk', -} - export interface UserRiskScoreItem { _id?: Maybe; - [UserRiskScoreFields.userName]: Maybe; - [UserRiskScoreFields.risk]: Maybe; - [UserRiskScoreFields.riskScore]: Maybe; + [RiskScoreFields.userName]: Maybe; + [RiskScoreFields.userRisk]: Maybe; + [RiskScoreFields.userRiskScore]: Maybe; } export interface UserItem { diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.test.tsx index 945317036e7bcb..0c6cf454e73eec 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.test.tsx @@ -11,10 +11,11 @@ import { render } from '@testing-library/react'; import { TestProviders } from '../../../mock'; import { NO_HOST_RISK_DATA_DESCRIPTION } from './translations'; import { HostRiskSummary } from './host_risk_summary'; +import { RiskSeverity } from '../../../../../common/search_strategy'; describe('HostRiskSummary', () => { it('renders host risk data', () => { - const riskKeyword = 'test risk'; + const riskSeverity = RiskSeverity.low; const hostRisk = { loading: false, isModuleEnabled: true, @@ -23,11 +24,12 @@ describe('HostRiskSummary', () => { '@timestamp': '1641902481', host: { name: 'test-host-name', - }, - risk: riskKeyword, - risk_stats: { - risk_score: 9999, - rule_risks: [], + risk: { + multipliers: [], + calculated_score_norm: 9999, + calculated_level: riskSeverity, + rule_risks: [], + }, }, }, ], @@ -39,7 +41,7 @@ describe('HostRiskSummary', () => { ); - expect(getByText(riskKeyword)).toBeInTheDocument(); + expect(getByText(riskSeverity)).toBeInTheDocument(); }); it('renders spinner when loading', () => { @@ -67,11 +69,12 @@ describe('HostRiskSummary', () => { '@timestamp': '1641902530', host: { name: 'test-host-name', - }, - risk: 'test-risk', - risk_stats: { - risk_score: 9999, - rule_risks: [], + risk: { + multipliers: [], + calculated_score_norm: 9999, + calculated_level: RiskSeverity.low, + rule_risks: [], + }, }, }, ], diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx index 078fb0e1442cdb..9f425da6475d77 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx @@ -12,7 +12,6 @@ import * as i18n from './translations'; import { RISKY_HOSTS_DOC_LINK } from '../../../../overview/components/overview_risky_host_links/risky_hosts_disabled_module'; import { EnrichedDataRow, ThreatSummaryPanelHeader } from './threat_summary_view'; import { RiskScore } from '../../severity/common'; -import type { RiskSeverity } from '../../../../../common/search_strategy'; import type { HostRisk } from '../../../../risk_score/containers'; const HostRiskSummaryComponent: React.FC<{ @@ -25,12 +24,12 @@ const HostRiskSummaryComponent: React.FC<{ toolTipContent={ @@ -56,7 +55,10 @@ const HostRiskSummaryComponent: React.FC<{ + } /> diff --git a/x-pack/plugins/security_solution/public/common/components/risk_score_over_time/index.tsx b/x-pack/plugins/security_solution/public/common/components/risk_score_over_time/index.tsx index 5c6979fbd4a039..d17621ade7956f 100644 --- a/x-pack/plugins/security_solution/public/common/components/risk_score_over_time/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/risk_score_over_time/index.tsx @@ -27,13 +27,14 @@ import { HeaderSection } from '../header_section'; import { InspectButton, InspectButtonContainer } from '../inspect'; import * as i18n from './translations'; import { PreferenceFormattedDate } from '../formatted_date'; -import type { RiskScore } from '../../../../common/search_strategy'; +import type { HostRiskScore, UserRiskScore } from '../../../../common/search_strategy'; +import { isUserRiskScore } from '../../../../common/search_strategy'; export interface RiskScoreOverTimeProps { from: string; to: string; loading: boolean; - riskScore?: RiskScore[]; + riskScore?: Array; queryId: string; title: string; toggleStatus: boolean; @@ -81,7 +82,7 @@ const RiskScoreOverTimeComponent: React.FC = ({ riskScore ?.map((data) => ({ x: data['@timestamp'], - y: data.risk_stats.risk_score, + y: (isUserRiskScore(data) ? data.user : data.host).risk.calculated_score_norm, })) .reverse() ?? [], [riskScore] diff --git a/x-pack/plugins/security_solution/public/common/mock/global_state.ts b/x-pack/plugins/security_solution/public/common/mock/global_state.ts index 00ca0e0a5852cd..d0d5fb0cd2cc5d 100644 --- a/x-pack/plugins/security_solution/public/common/mock/global_state.ts +++ b/x-pack/plugins/security_solution/public/common/mock/global_state.ts @@ -82,7 +82,7 @@ export const mockGlobalState: State = { hostRisk: { activePage: 0, limit: 10, - sort: { field: RiskScoreFields.riskScore, direction: Direction.desc }, + sort: { field: RiskScoreFields.hostRiskScore, direction: Direction.desc }, severitySelection: [], }, sessions: { activePage: 0, limit: 10 }, @@ -106,7 +106,7 @@ export const mockGlobalState: State = { hostRisk: { activePage: 0, limit: 10, - sort: { field: RiskScoreFields.riskScore, direction: Direction.desc }, + sort: { field: RiskScoreFields.hostRiskScore, direction: Direction.desc }, severitySelection: [], }, sessions: { activePage: 0, limit: 10 }, diff --git a/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx index 5d95d6e7f9446b..11d3575a27567e 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx @@ -129,9 +129,9 @@ const HostRiskInformationFlyout = ({ handleOnClose }: { handleOnClose: () => voi <> diff --git a/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx index 38daf27402c545..9a2138786b3a87 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/host_risk_score_table/index.tsx @@ -16,7 +16,7 @@ import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; import { hostsActions, hostsModel, hostsSelectors } from '../../store'; import { getHostRiskScoreColumns } from './columns'; import type { - HostsRiskScore, + HostRiskScore, RiskScoreItem, RiskScoreSortField, RiskSeverity, @@ -50,7 +50,7 @@ const IconWrapper = styled.span` const tableType = hostsModel.HostsTableType.risk; interface HostRiskScoreTableProps { - data: HostsRiskScore[]; + data: HostRiskScore[]; id: string; isInspect: boolean; loading: boolean; @@ -63,8 +63,8 @@ interface HostRiskScoreTableProps { export type HostRiskScoreColumns = [ Columns, - Columns, - Columns + Columns, + Columns ]; const HostRiskScoreTableComponent: React.FC = ({ diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx index b8e62a9bed97c1..145b9ec56a3442 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx @@ -28,7 +28,7 @@ import { SecuritySolutionPageWrapper } from '../../common/components/page_wrappe import { useGlobalFullScreen } from '../../common/containers/use_full_screen'; import { useGlobalTime } from '../../common/containers/use_global_time'; import { TimelineId } from '../../../common/types/timeline'; -import { LastEventIndexKey } from '../../../common/search_strategy'; +import { LastEventIndexKey, RiskScoreEntity } from '../../../common/search_strategy'; import { useKibana } from '../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../common/lib/keury'; import type { State } from '../../common/store'; @@ -103,7 +103,7 @@ const HostsComponent = () => { } if (tabName === HostsTableType.risk) { - const severityFilter = generateSeverityFilter(severitySelection); + const severityFilter = generateSeverityFilter(severitySelection, RiskScoreEntity.host); return [...severityFilter, ...hostNameExistsFilter, ...filters]; } diff --git a/x-pack/plugins/security_solution/public/hosts/pages/navigation/host_risk_tab_body.tsx b/x-pack/plugins/security_solution/public/hosts/pages/navigation/host_risk_tab_body.tsx index 67c9bb761be94d..33565cd9a34e11 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/navigation/host_risk_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/navigation/host_risk_tab_body.tsx @@ -9,6 +9,7 @@ import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; +import { last } from 'lodash/fp'; import type { HostsComponentsQueryProps } from './types'; import * as i18n from '../translations'; import { HostRiskInformationButtonEmpty } from '../../components/host_risk_information'; @@ -86,7 +87,7 @@ const HostRiskTabBodyComponent: React.FC< [setOverTimeToggleStatus] ); - const rules = data && data.length > 0 ? data[data.length - 1].risk_stats.rule_risks : []; + const lastHostRiskItem = last(data); return ( <> @@ -110,7 +111,7 @@ const HostRiskTabBodyComponent: React.FC< queryId={QUERY_ID} toggleStatus={contributorsToggleStatus} toggleQuery={toggleContributorsQuery} - rules={rules} + rules={lastHostRiskItem ? lastHostRiskItem.host.risk.rule_risks : []} /> diff --git a/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts b/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts index fd4830f93159fc..daaa2e54ca300e 100644 --- a/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts @@ -40,7 +40,7 @@ export const mockHostsState: HostsModel = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: RiskScoreFields.riskScore, + field: RiskScoreFields.hostRiskScore, direction: Direction.desc, }, severitySelection: [], @@ -79,7 +79,7 @@ export const mockHostsState: HostsModel = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: RiskScoreFields.riskScore, + field: RiskScoreFields.hostRiskScore, direction: Direction.desc, }, severitySelection: [], @@ -124,7 +124,7 @@ describe('Hosts redux store', () => { severitySelection: [], sort: { direction: 'desc', - field: 'risk_stats.risk_score', + field: RiskScoreFields.hostRiskScore, }, }, [HostsTableType.sessions]: { @@ -164,7 +164,7 @@ describe('Hosts redux store', () => { severitySelection: [], sort: { direction: 'desc', - field: 'risk_stats.risk_score', + field: RiskScoreFields.hostRiskScore, }, }, [HostsTableType.sessions]: { diff --git a/x-pack/plugins/security_solution/public/hosts/store/helpers.ts b/x-pack/plugins/security_solution/public/hosts/store/helpers.ts index 6093a2c72a3a9c..eaf1bb5d7c5aa8 100644 --- a/x-pack/plugins/security_solution/public/hosts/store/helpers.ts +++ b/x-pack/plugins/security_solution/public/hosts/store/helpers.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { RiskScoreEntity, RiskScoreFields } from '../../../common/search_strategy'; import type { RiskSeverity } from '../../../common/search_strategy'; import { DEFAULT_TABLE_ACTIVE_PAGE } from '../../common/store/constants'; @@ -60,7 +61,10 @@ export const setHostsQueriesActivePageToZero = (state: HostsModel, type: HostsTy throw new Error(`HostsType ${type} is unknown`); }; -export const generateSeverityFilter = (severitySelection: RiskSeverity[]) => +export const generateSeverityFilter = ( + severitySelection: RiskSeverity[], + entity: RiskScoreEntity +) => severitySelection.length > 0 ? [ { @@ -68,7 +72,9 @@ export const generateSeverityFilter = (severitySelection: RiskSeverity[]) => bool: { should: severitySelection.map((query) => ({ match_phrase: { - 'risk.keyword': { + [entity === RiskScoreEntity.user + ? RiskScoreFields.userRisk + : RiskScoreFields.hostRisk]: { query, }, }, diff --git a/x-pack/plugins/security_solution/public/hosts/store/reducer.ts b/x-pack/plugins/security_solution/public/hosts/store/reducer.ts index 15f4d979a7267f..f549b07b3850b2 100644 --- a/x-pack/plugins/security_solution/public/hosts/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/hosts/store/reducer.ts @@ -59,7 +59,7 @@ export const initialHostsState: HostsState = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: RiskScoreFields.riskScore, + field: RiskScoreFields.hostRiskScore, direction: Direction.desc, }, severitySelection: [], @@ -98,7 +98,7 @@ export const initialHostsState: HostsState = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: RiskScoreFields.riskScore, + field: RiskScoreFields.hostRiskScore, direction: Direction.desc, }, severitySelection: [], diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.test.tsx index b382e6905a60f0..feed7baf8819af 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.test.tsx @@ -84,7 +84,7 @@ describe('RiskScoreDonutChart', () => { expect(mockDispatch).toHaveBeenCalledWith( usersActions.updateTableSorting({ - sort: { field: RiskScoreFields.riskScore, direction: Direction.desc }, + sort: { field: RiskScoreFields.userRiskScore, direction: Direction.desc }, tableType: UsersTableType.risk, }) ); @@ -110,7 +110,7 @@ describe('RiskScoreDonutChart', () => { expect(mockDispatch).toHaveBeenCalledWith( hostsActions.updateHostRiskScoreSort({ - sort: { field: RiskScoreFields.riskScore, direction: Direction.desc }, + sort: { field: RiskScoreFields.hostRiskScore, direction: Direction.desc }, hostsType: HostsType.page, }) ); diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.tsx index dd22104bf39ad1..4ee2bab00f1db0 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/header/index.tsx @@ -52,7 +52,7 @@ export const EntityAnalyticsHeader = () => { dispatch( hostsActions.updateHostRiskScoreSort({ - sort: { field: RiskScoreFields.riskScore, direction: Direction.desc }, + sort: { field: RiskScoreFields.hostRiskScore, direction: Direction.desc }, hostsType: HostsType.page, }) ); @@ -74,7 +74,7 @@ export const EntityAnalyticsHeader = () => { dispatch( usersActions.updateTableSorting({ - sort: { field: RiskScoreFields.riskScore, direction: Direction.desc }, + sort: { field: RiskScoreFields.userRiskScore, direction: Direction.desc }, tableType: UsersTableType.risk, }) ); diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/columns.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/columns.tsx index affbd9e3357e6c..998a356bf4f738 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/columns.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/columns.tsx @@ -12,10 +12,11 @@ import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { HostDetailsLink } from '../../../../common/components/links'; import { HostsTableType } from '../../../../hosts/store/model'; import { RiskScore } from '../../../../common/components/severity/common'; -import type { HostsRiskScore, RiskSeverity } from '../../../../../common/search_strategy'; +import type { HostRiskScore, RiskSeverity } from '../../../../../common/search_strategy'; +import { RiskScoreFields } from '../../../../../common/search_strategy'; import * as i18n from './translations'; -type HostRiskScoreColumns = Array>; +type HostRiskScoreColumns = Array>; export const getHostRiskScoreColumns = (): HostRiskScoreColumns => [ { @@ -31,7 +32,7 @@ export const getHostRiskScoreColumns = (): HostRiskScoreColumns => [ }, }, { - field: 'risk_stats.risk_score', + field: RiskScoreFields.hostRiskScore, name: i18n.HOST_RISK_SCORE, truncateText: true, mobileOptions: { show: true }, @@ -47,7 +48,7 @@ export const getHostRiskScoreColumns = (): HostRiskScoreColumns => [ }, }, { - field: 'risk', + field: RiskScoreFields.hostRisk, name: ( <> diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx index 9e44561e8b4f5a..fa3cda0921c83a 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/host_risk_score/index.tsx @@ -27,6 +27,7 @@ import { HeaderSection } from '../../../../common/components/header_section'; import { useHostRiskScore, useHostRiskScoreKpi } from '../../../../risk_score/containers'; import type { RiskSeverity } from '../../../../../common/search_strategy'; +import { RiskScoreEntity } from '../../../../../common/search_strategy'; import { SecurityPageName } from '../../../../app/types'; import * as i18n from './translations'; import { generateSeverityFilter } from '../../../../hosts/store/helpers'; @@ -58,7 +59,7 @@ export const EntityAnalyticsHostRiskScores = () => { const riskyHostsFeatureEnabled = useIsExperimentalFeatureEnabled('riskyHostsEnabled'); const severityFilter = useMemo(() => { - const [filter] = generateSeverityFilter(selectedSeverity); + const [filter] = generateSeverityFilter(selectedSeverity, RiskScoreEntity.host); return filter ? JSON.stringify(filter.query) : undefined; }, [selectedSeverity]); @@ -127,7 +128,7 @@ export const EntityAnalyticsHostRiskScores = () => { return null; } - if (!isModuleEnabled) { + if (!isModuleEnabled && !isTableLoading) { return ; } diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/columns.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/columns.tsx index c32c2282f367e1..05f532617d5cca 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/columns.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/columns.tsx @@ -12,10 +12,11 @@ import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { RiskScore } from '../../../../common/components/severity/common'; import * as i18n from './translations'; import { UsersTableType } from '../../../../users/store/model'; -import type { RiskSeverity, UsersRiskScore } from '../../../../../common/search_strategy'; +import type { RiskSeverity, UserRiskScore } from '../../../../../common/search_strategy'; +import { RiskScoreFields } from '../../../../../common/search_strategy'; import { UserDetailsLink } from '../../../../common/components/links'; -type UserRiskScoreColumns = Array>; +type UserRiskScoreColumns = Array>; export const getUserRiskScoreColumns = (): UserRiskScoreColumns => [ { @@ -31,7 +32,7 @@ export const getUserRiskScoreColumns = (): UserRiskScoreColumns => [ }, }, { - field: 'risk_stats.risk_score', + field: RiskScoreFields.userRiskScore, name: i18n.USER_RISK_SCORE, truncateText: true, mobileOptions: { show: true }, @@ -47,7 +48,7 @@ export const getUserRiskScoreColumns = (): UserRiskScoreColumns => [ }, }, { - field: 'risk', + field: RiskScoreFields.userRisk, name: ( <> diff --git a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx index 34c41ee2a00242..68ed1082f4c053 100644 --- a/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/entity_analytics/user_risk_score/index.tsx @@ -20,6 +20,7 @@ import { LinkButton, useGetSecuritySolutionLinkProps } from '../../../../common/ import { LastUpdatedAt } from '../../detection_response/utils'; import { HeaderSection } from '../../../../common/components/header_section'; import type { RiskSeverity } from '../../../../../common/search_strategy'; +import { RiskScoreEntity } from '../../../../../common/search_strategy'; import { SecurityPageName } from '../../../../app/types'; import * as i18n from './translations'; import { generateSeverityFilter } from '../../../../hosts/store/helpers'; @@ -55,7 +56,7 @@ export const EntityAnalyticsUserRiskScores = () => { const riskyUsersFeatureEnabled = useIsExperimentalFeatureEnabled('riskyUsersEnabled'); const severityFilter = useMemo(() => { - const [filter] = generateSeverityFilter(selectedSeverity); + const [filter] = generateSeverityFilter(selectedSeverity, RiskScoreEntity.user); return filter ? JSON.stringify(filter.query) : undefined; }, [selectedSeverity]); @@ -123,7 +124,7 @@ export const EntityAnalyticsUserRiskScores = () => { return null; } - if (!isModuleEnabled) { + if (!isModuleEnabled && !isTableLoading) { return ; } diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx index 48dea1e5d4b900..721cd5c73f2856 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.test.tsx @@ -82,11 +82,11 @@ describe('Host Summary Component', () => { { host: { name: 'testHostmame', - }, - risk, - risk_stats: { - rule_risks: [], - risk_score: riskScore, + risk: { + rule_risks: [], + calculated_score_norm: riskScore, + calculated_level: risk, + }, }, }, ], diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx index c6aad526117cd7..d3a1f601445fd0 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx @@ -10,7 +10,7 @@ import { euiLightVars as lightTheme, euiDarkVars as darkTheme } from '@kbn/ui-th import { getOr } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; -import type { HostItem, RiskSeverity } from '../../../../common/search_strategy'; +import type { HostItem } from '../../../../common/search_strategy'; import { buildHostNamesFilter } from '../../../../common/search_strategy'; import { DEFAULT_DARK_MODE } from '../../../../common/constants'; import type { DescriptionList } from '../../../../common/utility_types'; @@ -108,7 +108,9 @@ export const HostOverview = React.memo( title: i18n.HOST_RISK_SCORE, description: ( <> - {hostRiskData ? Math.round(hostRiskData.risk_stats.risk_score) : getEmptyTagValue()} + {hostRiskData + ? Math.round(hostRiskData.host.risk.calculated_score_norm) + : getEmptyTagValue()} ), }, @@ -118,7 +120,10 @@ export const HostOverview = React.memo( description: ( <> {hostRiskData ? ( - + ) : ( getEmptyTagValue() )} diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx index d5e77c478aa1d8..46956823d19615 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx @@ -24,6 +24,7 @@ import { useRiskyHostsDashboardLinks } from '../../containers/overview_risky_hos import { mockTheme } from '../overview_cti_links/mock'; import { RiskyHostsEnabledModule } from './risky_hosts_enabled_module'; import { useDashboardButtonHref } from '../../../common/hooks/use_dashboard_button_href'; +import { RiskSeverity } from '../../../../common/search_strategy'; jest.mock('../../../common/lib/kibana'); @@ -59,12 +60,13 @@ describe('RiskyHostsEnabledModule', () => { '@timestamp': '1641902481', host: { name: 'a', + risk: { + calculated_score_norm: 1, + rule_risks: [], + calculated_level: RiskSeverity.low, + multipliers: [], + }, }, - risk_stats: { - risk_score: 1, - rule_risks: [], - }, - risk: '', }, ]} to={'now'} diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx index fae3c4db217376..49a185d6e1513d 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx @@ -9,20 +9,20 @@ import React, { useMemo } from 'react'; import { RiskyHostsPanelView } from './risky_hosts_panel_view'; import type { LinkPanelListItem } from '../link_panel'; import { useRiskyHostsDashboardLinks } from '../../containers/overview_risky_host_links/use_risky_hosts_dashboard_links'; -import type { HostsRiskScore } from '../../../../common/search_strategy'; +import type { HostRiskScore } from '../../../../common/search_strategy'; -const getListItemsFromHits = (items: HostsRiskScore[]): LinkPanelListItem[] => { - return items.map(({ host, risk_stats: riskStats, risk: copy }) => ({ +const getListItemsFromHits = (items: HostRiskScore[]): LinkPanelListItem[] => { + return items.map(({ host }) => ({ title: host.name, - count: riskStats.risk_score, - copy, + count: host.risk.calculated_score_norm, + copy: host.risk.calculated_level, path: '', })); }; const RiskyHostsEnabledModuleComponent: React.FC<{ from: string; - hostRiskScore?: HostsRiskScore[]; + hostRiskScore?: HostRiskScore[]; to: string; }> = ({ hostRiskScore, to, from }) => { const listItems = useMemo(() => getListItemsFromHits(hostRiskScore || []), [hostRiskScore]); diff --git a/x-pack/plugins/security_solution/public/overview/components/user_overview/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/user_overview/index.test.tsx index 5cf51615a395d6..9bc5ce903e2caf 100644 --- a/x-pack/plugins/security_solution/public/overview/components/user_overview/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/user_overview/index.test.tsx @@ -93,13 +93,13 @@ describe('User Summary Component', () => { { data: [ { - host: { + user: { name: 'testUsermame', - }, - risk, - risk_stats: { - rule_risks: [], - risk_score: riskScore, + risk: { + rule_risks: [], + calculated_level: risk, + calculated_score_norm: riskScore, + }, }, }, ], diff --git a/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx b/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx index 6349a33a58fa33..6c5f4a952e9a71 100644 --- a/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx @@ -106,7 +106,9 @@ export const UserOverview = React.memo( title: i18n.USER_RISK_SCORE, description: ( <> - {userRiskData ? Math.round(userRiskData.risk_stats.risk_score) : getEmptyTagValue()} + {userRiskData + ? Math.round(userRiskData.user.risk.calculated_score_norm) + : getEmptyTagValue()} ), }, @@ -115,7 +117,10 @@ export const UserOverview = React.memo( description: ( <> {userRiskData ? ( - + ) : ( getEmptyTagValue() )} diff --git a/x-pack/plugins/security_solution/public/risk_score/containers/index.ts b/x-pack/plugins/security_solution/public/risk_score/containers/index.ts index 56e3ff14ce1484..323a6d26acb346 100644 --- a/x-pack/plugins/security_solution/public/risk_score/containers/index.ts +++ b/x-pack/plugins/security_solution/public/risk_score/containers/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { HostsRiskScore } from '../../../common/search_strategy/security_solution/risk_score'; +import type { HostRiskScore } from '../../../common/search_strategy/security_solution/risk_score'; export * from './all'; export * from './kpi'; @@ -25,5 +25,5 @@ export const enum HostRiskScoreQueryId { export interface HostRisk { loading: boolean; isModuleEnabled?: boolean; - result?: HostsRiskScore[]; + result?: HostRiskScore[]; } diff --git a/x-pack/plugins/security_solution/public/risk_score/containers/kpi/index.tsx b/x-pack/plugins/security_solution/public/risk_score/containers/kpi/index.tsx index 396d86e2d6acc7..6d4ee5c73c5f67 100644 --- a/x-pack/plugins/security_solution/public/risk_score/containers/kpi/index.tsx +++ b/x-pack/plugins/security_solution/public/risk_score/containers/kpi/index.tsx @@ -16,13 +16,13 @@ import { createFilter } from '../../../common/containers/helpers'; import type { KpiRiskScoreRequestOptions, KpiRiskScoreStrategyResponse, - RiskScoreAggByFields, } from '../../../../common/search_strategy'; import { getHostRiskIndex, getUserRiskIndex, RiskQueries, RiskSeverity, + RiskScoreEntity, } from '../../../../common/search_strategy'; import { useKibana } from '../../../common/lib/kibana'; @@ -32,7 +32,7 @@ import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_exper import type { SeverityCount } from '../../../common/components/severity/types'; import { useSpaceId } from '../../../common/hooks/use_space_id'; -type GetHostsRiskScoreProps = KpiRiskScoreRequestOptions & { +type GetHostRiskScoreProps = KpiRiskScoreRequestOptions & { data: DataPublicPluginStart; signal: AbortSignal; }; @@ -42,14 +42,14 @@ const getRiskScoreKpi = ({ defaultIndex, signal, filterQuery, - aggBy, -}: GetHostsRiskScoreProps): Observable => + entity, +}: GetHostRiskScoreProps): Observable => data.search.search( { defaultIndex, factoryQueryType: RiskQueries.kpiRiskScore, filterQuery: createFilter(filterQuery), - aggBy, + entity, }, { strategy: 'securitySolutionSearchStrategy', @@ -58,7 +58,7 @@ const getRiskScoreKpi = ({ ); const getRiskScoreKpiComplete = ( - props: GetHostsRiskScoreProps + props: GetHostRiskScoreProps ): Observable => { return getRiskScoreKpi(props).pipe( filter((response) => { @@ -80,11 +80,11 @@ interface RiskScoreKpi { type UseHostRiskScoreKpiProps = Omit< UseRiskScoreKpiProps, - 'defaultIndex' | 'aggBy' | 'featureEnabled' + 'defaultIndex' | 'aggBy' | 'featureEnabled' | 'entity' >; type UseUserRiskScoreKpiProps = Omit< UseRiskScoreKpiProps, - 'defaultIndex' | 'aggBy' | 'featureEnabled' + 'defaultIndex' | 'aggBy' | 'featureEnabled' | 'entity' >; export const useUserRiskScoreKpi = ({ @@ -99,7 +99,7 @@ export const useUserRiskScoreKpi = ({ filterQuery, skip, defaultIndex, - aggBy: 'user.name', + entity: RiskScoreEntity.user, featureEnabled: riskyUsersFeatureEnabled, }); }; @@ -116,7 +116,7 @@ export const useHostRiskScoreKpi = ({ filterQuery, skip, defaultIndex, - aggBy: 'host.name', + entity: RiskScoreEntity.host, featureEnabled: riskyHostsFeatureEnabled, }); }; @@ -125,7 +125,7 @@ interface UseRiskScoreKpiProps { filterQuery?: string | ESTermQuery; skip?: boolean; defaultIndex: string | undefined; - aggBy: RiskScoreAggByFields; + entity: RiskScoreEntity; featureEnabled: boolean; } @@ -133,7 +133,7 @@ const useRiskScoreKpi = ({ filterQuery, skip, defaultIndex, - aggBy, + entity, featureEnabled, }: UseRiskScoreKpiProps): RiskScoreKpi => { const { error, result, start, loading } = useRiskScoreKpiComplete(); @@ -146,10 +146,10 @@ const useRiskScoreKpi = ({ data, filterQuery, defaultIndex: [defaultIndex], - aggBy, + entity, }); } - }, [data, defaultIndex, start, filterQuery, skip, aggBy, featureEnabled]); + }, [data, defaultIndex, start, filterQuery, skip, entity, featureEnabled]); const severityCount = useMemo( () => ({ @@ -162,5 +162,6 @@ const useRiskScoreKpi = ({ }), [result] ); + return { error, severityCount, loading, isModuleDisabled }; }; diff --git a/x-pack/plugins/security_solution/public/users/components/user_risk_information/index.tsx b/x-pack/plugins/security_solution/public/users/components/user_risk_information/index.tsx index 07fd273625d932..5da702eb877979 100644 --- a/x-pack/plugins/security_solution/public/users/components/user_risk_information/index.tsx +++ b/x-pack/plugins/security_solution/public/users/components/user_risk_information/index.tsx @@ -105,9 +105,9 @@ const UserRiskInformationFlyout = ({ handleOnClose }: { handleOnClose: () => voi { const defaultProps = { @@ -19,8 +20,8 @@ describe('getUserRiskScoreColumns', () => { const columns = getUserRiskScoreColumns(defaultProps); expect(columns[0].field).toBe('user.name'); - expect(columns[1].field).toBe('risk_stats.risk_score'); - expect(columns[2].field).toBe('risk'); + expect(columns[1].field).toBe(RiskScoreFields.userRiskScore); + expect(columns[2].field).toBe(RiskScoreFields.userRisk); columns.forEach((column) => { expect(column).toHaveProperty('name'); diff --git a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/columns.tsx b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/columns.tsx index 24ccfd3eb01f5d..c50ae488383f07 100644 --- a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/columns.tsx @@ -21,6 +21,7 @@ import type { UserRiskScoreColumns } from '.'; import * as i18n from './translations'; import { RiskScore } from '../../../common/components/severity/common'; import type { RiskSeverity } from '../../../../common/search_strategy'; +import { RiskScoreFields } from '../../../../common/search_strategy'; import { UserDetailsLink } from '../../../common/components/links'; import { UsersTableType } from '../../store/model'; @@ -68,7 +69,7 @@ export const getUserRiskScoreColumns = ({ }, }, { - field: 'risk_stats.risk_score', + field: RiskScoreFields.userRiskScore, name: i18n.USER_RISK_SCORE, truncateText: true, mobileOptions: { show: true }, @@ -85,7 +86,7 @@ export const getUserRiskScoreColumns = ({ }, }, { - field: 'risk', + field: RiskScoreFields.userRisk, name: ( <> diff --git a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.test.tsx b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.test.tsx index c0cd2e351298e4..34f0116bb055e1 100644 --- a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.test.tsx @@ -9,6 +9,8 @@ import { render } from '@testing-library/react'; import { noop } from 'lodash'; import React from 'react'; import { UserRiskScoreTable } from '.'; +import type { UserRiskScore } from '../../../../common/search_strategy'; +import { RiskSeverity } from '../../../../common/search_strategy'; import { TestProviders } from '../../../common/mock'; import { UsersType } from '../../store/model'; @@ -18,16 +20,17 @@ describe('UserRiskScoreTable', () => { data: [ { '@timestamp': '1641902481', - risk: 'High', - risk_stats: { - rule_risks: [], - risk_score: 71, - }, user: { name: username, + risk: { + rule_risks: [], + calculated_score_norm: 71, + calculated_level: RiskSeverity.high, + multipliers: [], + }, }, }, - ], + ] as UserRiskScore[], id: 'test_id', isInspect: false, loading: false, diff --git a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx index 96a81ab4f50733..245150f4fb49db 100644 --- a/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx +++ b/x-pack/plugins/security_solution/public/users/components/user_risk_score_table/index.tsx @@ -18,10 +18,7 @@ import { getUserRiskScoreColumns } from './columns'; import * as i18nUsers from '../../pages/translations'; import * as i18n from './translations'; import { usersModel, usersSelectors, usersActions } from '../../store'; -import type { - UserRiskScoreFields, - UserRiskScoreItem, -} from '../../../../common/search_strategy/security_solution/users/common'; +import type { UserRiskScoreItem } from '../../../../common/search_strategy/security_solution/users/common'; import type { SeverityCount } from '../../../common/components/severity/types'; import { SeverityBadges } from '../../../common/components/severity/severity_badges'; import { SeverityBar } from '../../../common/components/severity/severity_bar'; @@ -29,9 +26,10 @@ import { SeverityFilterGroup } from '../../../common/components/severity/severit import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; import type { State } from '../../../common/store'; import type { + RiskScoreFields, RiskScoreSortField, RiskSeverity, - UsersRiskScore, + UserRiskScore, } from '../../../../common/search_strategy'; const IconWrapper = styled.span` @@ -52,7 +50,7 @@ export const rowItems: ItemsPerRow[] = [ const tableType = usersModel.UsersTableType.risk; interface UserRiskScoreTableProps { - data: UsersRiskScore[]; + data: UserRiskScore[]; id: string; isInspect: boolean; loading: boolean; @@ -64,9 +62,9 @@ interface UserRiskScoreTableProps { } export type UserRiskScoreColumns = [ - Columns, - Columns, - Columns + Columns, + Columns, + Columns ]; const UserRiskScoreTableComponent: React.FC = ({ @@ -170,7 +168,7 @@ const UserRiskScoreTableComponent: React.FC = ({ ); const getUserRiskScoreFilterQuerySelector = useMemo( - () => usersSelectors.usersRiskScoreSeverityFilterSelector(), + () => usersSelectors.userRiskScoreSeverityFilterSelector(), [] ); const severitySelectionRedux = useDeepEqualSelector((state: State) => diff --git a/x-pack/plugins/security_solution/public/users/pages/navigation/user_risk_tab_body.tsx b/x-pack/plugins/security_solution/public/users/pages/navigation/user_risk_tab_body.tsx index cef4740500a979..de45a4cdeeba4c 100644 --- a/x-pack/plugins/security_solution/public/users/pages/navigation/user_risk_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/users/pages/navigation/user_risk_tab_body.tsx @@ -16,6 +16,7 @@ import { RiskScoreOverTime } from '../../../common/components/risk_score_over_ti import { TopRiskScoreContributors } from '../../../common/components/top_risk_score_contributors'; import { useQueryToggle } from '../../../common/containers/query_toggle'; import { UserRiskScoreQueryId, useUserRiskScore } from '../../../risk_score/containers'; +import type { UserRiskScore } from '../../../../common/search_strategy'; import { buildUserNamesFilter } from '../../../../common/search_strategy'; import type { UsersComponentsQueryProps } from './types'; import { UserRiskInformationButtonEmpty } from '../../components/user_risk_information'; @@ -86,7 +87,9 @@ const UserRiskTabBodyComponent: React.FC< [setOverTimeToggleStatus] ); - const rules = data && data.length > 0 ? data[data.length - 1].risk_stats.rule_risks : []; + const lastUsertRiskItem: UserRiskScore | null = + data && data.length > 0 ? data[data.length - 1] : null; + const rules = lastUsertRiskItem ? lastUsertRiskItem.user.risk.rule_risks : []; return ( <> diff --git a/x-pack/plugins/security_solution/public/users/pages/users.tsx b/x-pack/plugins/security_solution/public/users/pages/users.tsx index 01b239ee89b489..94345fa24f3777 100644 --- a/x-pack/plugins/security_solution/public/users/pages/users.tsx +++ b/x-pack/plugins/security_solution/public/users/pages/users.tsx @@ -45,7 +45,7 @@ import { useDeepEqualSelector } from '../../common/hooks/use_selector'; import { useInvalidFilterQuery } from '../../common/hooks/use_invalid_filter_query'; import { UsersKpiComponent } from '../components/kpi_users'; import type { UpdateDateRange } from '../../common/components/charts/common'; -import { LastEventIndexKey } from '../../../common/search_strategy'; +import { LastEventIndexKey, RiskScoreEntity } from '../../../common/search_strategy'; import { generateSeverityFilter } from '../../hosts/store/helpers'; import { UsersTableType } from '../store/model'; import { hasMlUserPermissions } from '../../../common/machine_learning/has_ml_user_permissions'; @@ -77,12 +77,12 @@ const UsersComponent = () => { const query = useDeepEqualSelector(getGlobalQuerySelector); const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); - const getUsersRiskScoreFilterQuerySelector = useMemo( - () => usersSelectors.usersRiskScoreSeverityFilterSelector(), + const getUserRiskScoreFilterQuerySelector = useMemo( + () => usersSelectors.userRiskScoreSeverityFilterSelector(), [] ); const severitySelection = useDeepEqualSelector((state: State) => - getUsersRiskScoreFilterQuerySelector(state) + getUserRiskScoreFilterQuerySelector(state) ); const { to, from, deleteQuery, setQuery, isInitializing } = useGlobalTime(); @@ -96,7 +96,7 @@ const UsersComponent = () => { } if (tabName === UsersTableType.risk) { - const severityFilter = generateSeverityFilter(severitySelection); + const severityFilter = generateSeverityFilter(severitySelection, RiskScoreEntity.user); return [...severityFilter, ...filters]; } diff --git a/x-pack/plugins/security_solution/public/users/store/model.ts b/x-pack/plugins/security_solution/public/users/store/model.ts index de9606d1639446..bee5eca0d71987 100644 --- a/x-pack/plugins/security_solution/public/users/store/model.ts +++ b/x-pack/plugins/security_solution/public/users/store/model.ts @@ -37,7 +37,7 @@ export interface AllUsersQuery extends BasicQueryPaginated { sort: SortUsersField; } -export interface UsersRiskScoreQuery extends BasicQueryPaginated { +export interface UserRiskScoreQuery extends BasicQueryPaginated { sort: RiskScoreSortField; severitySelection: RiskSeverity[]; } @@ -51,7 +51,7 @@ export interface UsersQueries { [UsersTableType.allUsers]: AllUsersQuery; [UsersTableType.authentications]: BasicQueryPaginated; [UsersTableType.anomalies]: UsersAnomaliesQuery; - [UsersTableType.risk]: UsersRiskScoreQuery; + [UsersTableType.risk]: UserRiskScoreQuery; [UsersTableType.events]: BasicQueryPaginated; } diff --git a/x-pack/plugins/security_solution/public/users/store/reducer.ts b/x-pack/plugins/security_solution/public/users/store/reducer.ts index 0699f3d3c3acc3..79e9511bbd6f0c 100644 --- a/x-pack/plugins/security_solution/public/users/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/users/store/reducer.ts @@ -44,7 +44,7 @@ export const initialUsersState: UsersModel = { activePage: DEFAULT_TABLE_ACTIVE_PAGE, limit: DEFAULT_TABLE_LIMIT, sort: { - field: RiskScoreFields.riskScore, + field: RiskScoreFields.userRiskScore, direction: Direction.desc, }, severitySelection: [], diff --git a/x-pack/plugins/security_solution/public/users/store/selectors.ts b/x-pack/plugins/security_solution/public/users/store/selectors.ts index db054c88cf3add..eb69c941fa2361 100644 --- a/x-pack/plugins/security_solution/public/users/store/selectors.ts +++ b/x-pack/plugins/security_solution/public/users/store/selectors.ts @@ -23,7 +23,7 @@ export const allUsersSelector = () => export const userRiskScoreSelector = () => createSelector(selectUserPage, (users) => users.queries[UsersTableType.risk]); -export const usersRiskScoreSeverityFilterSelector = () => +export const userRiskScoreSeverityFilterSelector = () => createSelector(selectUserPage, (users) => users.queries[UsersTableType.risk].severitySelection); export const authenticationsSelector = () => diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.test.ts index b0b2292d6b5f14..d21bc53de178f8 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.test.ts @@ -91,6 +91,12 @@ describe('allHosts search strategy', () => { risk, host: { name: hostName, + risk: { + multipliers: [], + calculated_score_norm: 9999, + calculated_level: risk, + rule_risks: [], + }, }, }, }, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts index 57f30ed8703b07..cecfc60fbbaed8 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/index.ts @@ -18,7 +18,7 @@ import type { HostsEdges, } from '../../../../../../common/search_strategy/security_solution/hosts'; -import type { HostsRiskScore } from '../../../../../../common/search_strategy'; +import type { HostRiskScore } from '../../../../../../common/search_strategy'; import { getHostRiskIndex, buildHostNamesFilter } from '../../../../../../common/search_strategy'; import { inspectStringifyObject } from '../../../../../utils/build_query'; @@ -92,7 +92,7 @@ async function enhanceEdges( const hostsRiskByHostName: Record | undefined = hostRiskData?.hits.hits.reduce( (acc, hit) => ({ ...acc, - [hit._source?.host.name ?? '']: hit._source?.risk, + [hit._source?.host.name ?? '']: hit._source?.host.risk.calculated_level, }), {} ); @@ -114,7 +114,7 @@ async function getHostRiskData( hostNames: string[] ) { try { - const hostRiskResponse = await esClient.asCurrentUser.search( + const hostRiskResponse = await esClient.asCurrentUser.search( buildRiskScoreQuery({ defaultIndex: [getHostRiskIndex(spaceId)], filterQuery: buildHostNamesFilter(hostNames), diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/all/query.risk_score.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/all/query.risk_score.dsl.ts index 069a3e01cdbc1d..d4ec14bb29acfb 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/all/query.risk_score.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/all/query.risk_score.dsl.ts @@ -64,8 +64,12 @@ const getQueryOrder = (sort?: RiskScoreSortField): Sort => { ]; } - if (sort.field === RiskScoreFields.risk) { - return [{ [RiskScoreFields.riskScore]: sort.direction }]; + if (sort.field === RiskScoreFields.hostRisk) { + return [{ [RiskScoreFields.hostRiskScore]: sort.direction }]; + } + + if (sort.field === RiskScoreFields.userRisk) { + return [{ [RiskScoreFields.userRiskScore]: sort.direction }]; } return [{ [sort.field]: sort.direction }]; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/__mocks__/index.ts index 94830d71e6337e..e494849cc6cebc 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/__mocks__/index.ts @@ -6,7 +6,7 @@ */ import type { KpiRiskScoreRequestOptions } from '../../../../../../../common/search_strategy'; -import { RiskQueries } from '../../../../../../../common/search_strategy'; +import { RiskScoreEntity, RiskQueries } from '../../../../../../../common/search_strategy'; export const mockOptions: KpiRiskScoreRequestOptions = { defaultIndex: [ @@ -22,5 +22,5 @@ export const mockOptions: KpiRiskScoreRequestOptions = { factoryQueryType: RiskQueries.kpiRiskScore, filterQuery: '{"bool":{"must":[],"filter":[{"match_all":{}},{"bool":{"filter":[{"bool":{"should":[{"exists":{"field":"host.name"}}],"minimum_should_match":1}}]}}],"should":[],"must_not":[]}}', - aggBy: 'host.name', + entity: RiskScoreEntity.host, }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/query.kpi_risk_score.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/query.kpi_risk_score.dsl.ts index ace0cece7c9814..f68eb647ad88c6 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/query.kpi_risk_score.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/risk_score/kpi/query.kpi_risk_score.dsl.ts @@ -5,13 +5,14 @@ * 2.0. */ +import { RiskScoreEntity, RiskScoreFields } from '../../../../../../common/search_strategy'; import type { KpiRiskScoreRequestOptions } from '../../../../../../common/search_strategy'; import { createQueryFilterClauses } from '../../../../../utils/build_query'; export const buildKpiRiskScoreQuery = ({ defaultIndex, filterQuery, - aggBy, + entity, }: KpiRiskScoreRequestOptions) => { const filter = [...createQueryFilterClauses(filterQuery)]; @@ -24,12 +25,16 @@ export const buildKpiRiskScoreQuery = ({ aggs: { risk: { terms: { - field: 'risk.keyword', + field: + entity === RiskScoreEntity.user ? RiskScoreFields.userRisk : RiskScoreFields.hostRisk, }, aggs: { unique_entries: { cardinality: { - field: aggBy, + field: + entity === RiskScoreEntity.user + ? RiskScoreFields.userName + : RiskScoreFields.hostName, }, }, }, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 43b3cbacf2a8df..3f545e9c87229d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -25210,7 +25210,6 @@ "xpack.security.unauthenticated.pageTitle": "Impossible de vous connecter", "xpack.security.users.breadcrumb": "Utilisateurs", "xpack.security.users.editUserPage.createBreadcrumb": "Créer", - "xpack.securitySolution.alertDetails.overview.hostDataTooltipContent": "La classification des risques n’est affichée que lorsqu’elle est disponible pour un hôte. Vérifiez que {hostsRiskScoreDocumentationLink} est activé dans votre environnement.", "xpack.securitySolution.alertDetails.overview.insights_related_alerts_by_source_event_count": "{count} {count, plural, =1 {alerte} other {alertes}} par événement source", "xpack.securitySolution.alertDetails.overview.insights_related_cases_found_content": "Cette alerte a été détectée dans {caseCount}", "xpack.securitySolution.alertDetails.overview.insights_related_cases_found_content_count": "{caseCount} {caseCount, plural, =0 {cas.} =1 {cas :} other {cas :}}", @@ -25466,7 +25465,6 @@ "xpack.securitySolution.hostIsolationExceptions.flyoutCreateSubmitSuccess": "\"{name}\" a été ajouté à votre liste d'exceptions d'isolation de l'hôte.", "xpack.securitySolution.hostIsolationExceptions.flyoutEditSubmitSuccess": "\"{name}\" a été mis à jour.", "xpack.securitySolution.hostIsolationExceptions.showingTotal": "Affichage de {total} {total, plural, one {exception d'isolation de l'hôte} other {exceptions d'isolation de l'hôte}}", - "xpack.securitySolution.hosts.hostRiskInformation.learnMore": "Pour en savoir plus sur le risque de l'hôte, cliquez {hostsRiskScoreDocumentationLink}", "xpack.securitySolution.hosts.navigaton.eventsUnit": "{totalCount, plural, =1 {événement} other {événements}}", "xpack.securitySolution.hostsRiskTable.filteredHostsTitle": "Afficher les hôtes à risque {severity}", "xpack.securitySolution.hostsTable.rows": "{numRows} {numRows, plural, =0 {ligne} =1 {ligne} other {lignes}}", @@ -25594,7 +25592,6 @@ "xpack.securitySolution.uncommonProcessTable.unit": "{totalCount, plural, other {processus}}", "xpack.securitySolution.useInputHints.exampleInstructions": "Ex : [ {exampleUsage} ]", "xpack.securitySolution.useInputHints.unknownCommand": "Commande inconnue {commandName}", - "xpack.securitySolution.users.userRiskInformation.learnMore": "Pour en savoir plus sur le risque de l'utilisateur, cliquez {usersRiskScoreDocumentationLink}", "xpack.securitySolution.usersRiskTable.filteredUsersTitle": "Afficher les utilisateurs à risque {severity}", "xpack.securitySolution.usersTable.rows": "{numRows} {numRows, plural, =0 {ligne} =1 {ligne} other {lignes}}", "xpack.securitySolution.usersTable.unit": "{totalCount, plural, =1 {utilisateur} other {utilisateurs}}", @@ -25619,7 +25616,6 @@ "xpack.securitySolution.alertDetails.overview.highlightedFields.field": "Champ", "xpack.securitySolution.alertDetails.overview.highlightedFields.value": "Valeur", "xpack.securitySolution.alertDetails.overview.hostRiskDataTitle": "Données de risque de l’hôte", - "xpack.securitySolution.alertDetails.overview.hostsRiskScoreLink": "Score de risque de l’hôte", "xpack.securitySolution.alertDetails.overview.insights": "Informations exploitables", "xpack.securitySolution.alertDetails.overview.insights.related_alerts_by_process_ancestry": "Alertes connexes par processus ancêtre", "xpack.securitySolution.alertDetails.overview.insights.related_alerts_by_process_ancestry_error": "Impossible de récupérer les alertes.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 1d8efe71c1530e..75b6e829bd3e77 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25189,7 +25189,6 @@ "xpack.security.unauthenticated.pageTitle": "ログインできませんでした", "xpack.security.users.breadcrumb": "ユーザー", "xpack.security.users.editUserPage.createBreadcrumb": "作成", - "xpack.securitySolution.alertDetails.overview.hostDataTooltipContent": "リスク分類は、ホストで使用可能なときにのみ表示されます。環境内で{hostsRiskScoreDocumentationLink}が有効であることを確認してください。", "xpack.securitySolution.alertDetails.overview.insights_related_alerts_by_source_event_count": "ソースイベントに関連する{count} {count, plural, other {件のアラート}}", "xpack.securitySolution.alertDetails.overview.insights_related_cases_found_content": "このアラートは{caseCount}で見つかりました", "xpack.securitySolution.alertDetails.overview.insights_related_cases_found_content_count": "{caseCount} {caseCount, plural, other {個のケース:}}", @@ -25443,7 +25442,6 @@ "xpack.securitySolution.hostIsolationExceptions.flyoutCreateSubmitSuccess": "\"{name}\"はホスト分離例外リストに追加されました。", "xpack.securitySolution.hostIsolationExceptions.flyoutEditSubmitSuccess": "\"{name}\"が更新されました。", "xpack.securitySolution.hostIsolationExceptions.showingTotal": "{total} {total, plural, other {個のホスト分離例外}}", - "xpack.securitySolution.hosts.hostRiskInformation.learnMore": "ホストリスクの詳細をご覧ください。{hostsRiskScoreDocumentationLink}", "xpack.securitySolution.hosts.navigaton.eventsUnit": "{totalCount, plural, other {イベント}}", "xpack.securitySolution.hostsRiskTable.filteredHostsTitle": "{severity}のリスクがあるホストを表示", "xpack.securitySolution.hostsTable.rows": "{numRows} {numRows, plural, other {行}}", @@ -25571,7 +25569,6 @@ "xpack.securitySolution.uncommonProcessTable.unit": "{totalCount, plural, other {プロセス}}", "xpack.securitySolution.useInputHints.exampleInstructions": "例:[ {exampleUsage} ]", "xpack.securitySolution.useInputHints.unknownCommand": "不明なコマンド{commandName}", - "xpack.securitySolution.users.userRiskInformation.learnMore": "ユーザーリスクの詳細をご覧ください。{usersRiskScoreDocumentationLink}", "xpack.securitySolution.usersRiskTable.filteredUsersTitle": "{severity}リスクのユーザーを表示", "xpack.securitySolution.usersTable.rows": "{numRows} {numRows, plural, other {行}}", "xpack.securitySolution.usersTable.unit": "{totalCount, plural, other {ユーザー}}", @@ -25596,7 +25593,6 @@ "xpack.securitySolution.alertDetails.overview.highlightedFields.field": "フィールド", "xpack.securitySolution.alertDetails.overview.highlightedFields.value": "値", "xpack.securitySolution.alertDetails.overview.hostRiskDataTitle": "ホストリスクデータ", - "xpack.securitySolution.alertDetails.overview.hostsRiskScoreLink": "ホストリスクスコア", "xpack.securitySolution.alertDetails.overview.insights": "インサイト", "xpack.securitySolution.alertDetails.overview.insights.related_alerts_by_process_ancestry": "上位プロセス別関連アラート", "xpack.securitySolution.alertDetails.overview.insights.related_alerts_by_process_ancestry_error": "アラートを取得できませんでした。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 120a031c7c9121..a1246cc1fa749b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25218,7 +25218,6 @@ "xpack.security.unauthenticated.pageTitle": "我们无法使您登录", "xpack.security.users.breadcrumb": "用户", "xpack.security.users.editUserPage.createBreadcrumb": "创建", - "xpack.securitySolution.alertDetails.overview.hostDataTooltipContent": "仅在其对主机可用时才会显示风险分类。确保在您的环境中启用了 {hostsRiskScoreDocumentationLink}。", "xpack.securitySolution.alertDetails.overview.insights_related_alerts_by_source_event_count": "{count} 个{count, plural, other {告警}}与源事件相关", "xpack.securitySolution.alertDetails.overview.insights_related_cases_found_content": "发现此告警位于 {caseCount}", "xpack.securitySolution.alertDetails.overview.insights_related_cases_found_content_count": "{caseCount} 个{caseCount, plural, other {案例:}}", @@ -25474,7 +25473,6 @@ "xpack.securitySolution.hostIsolationExceptions.flyoutCreateSubmitSuccess": "已将“{name}”添加到您的主机隔离例外列表。", "xpack.securitySolution.hostIsolationExceptions.flyoutEditSubmitSuccess": "“{name}”已更新。", "xpack.securitySolution.hostIsolationExceptions.showingTotal": "正在显示 {total} 个{total, plural, other {主机隔离例外}}", - "xpack.securitySolution.hosts.hostRiskInformation.learnMore": "您可以详细了解主机风险{hostsRiskScoreDocumentationLink}", "xpack.securitySolution.hosts.navigaton.eventsUnit": "{totalCount, plural, other {个事件}}", "xpack.securitySolution.hostsRiskTable.filteredHostsTitle": "查看{severity}风险主机", "xpack.securitySolution.hostsTable.rows": "{numRows} {numRows, plural, other {行}}", @@ -25602,7 +25600,6 @@ "xpack.securitySolution.uncommonProcessTable.unit": "{totalCount, plural, other {个进程}}", "xpack.securitySolution.useInputHints.exampleInstructions": "例如:[ {exampleUsage} ]", "xpack.securitySolution.useInputHints.unknownCommand": "未知命令 {commandName}", - "xpack.securitySolution.users.userRiskInformation.learnMore": "您可以详细了解用户风险{usersRiskScoreDocumentationLink}", "xpack.securitySolution.usersRiskTable.filteredUsersTitle": "查看{severity}风险用户", "xpack.securitySolution.usersTable.rows": "{numRows} {numRows, plural, other {行}}", "xpack.securitySolution.usersTable.unit": "{totalCount, plural, other {个用户}}", @@ -25627,7 +25624,6 @@ "xpack.securitySolution.alertDetails.overview.highlightedFields.field": "字段", "xpack.securitySolution.alertDetails.overview.highlightedFields.value": "值", "xpack.securitySolution.alertDetails.overview.hostRiskDataTitle": "主机风险数据", - "xpack.securitySolution.alertDetails.overview.hostsRiskScoreLink": "主机风险分数", "xpack.securitySolution.alertDetails.overview.insights": "洞见", "xpack.securitySolution.alertDetails.overview.insights.related_alerts_by_process_ancestry": "按进程体系列出相关告警", "xpack.securitySolution.alertDetails.overview.insights.related_alerts_by_process_ancestry_error": "无法获取告警。", diff --git a/x-pack/test/security_solution_cypress/es_archives/risky_hosts/data.json b/x-pack/test/security_solution_cypress/es_archives/risky_hosts/data.json index 3e468d7a84ca26..b10cd1b6a1c0d2 100644 --- a/x-pack/test/security_solution_cypress/es_archives/risky_hosts/data.json +++ b/x-pack/test/security_solution_cypress/es_archives/risky_hosts/data.json @@ -1,174 +1,174 @@ { - "type":"doc", - "value":{ - "id":"a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", - "index":"ml_host_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 21, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] + "type": "doc", + "value": { + "id": "a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", + "index": "ml_host_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "host": { + "name": "siem-kibana", + "risk": { + "calculated_level": "Low", + "calculated_score_norm": 21, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "host":{ - "name":"siem-kibana" - }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Low" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb71f", - "index":"ml_host_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] - }, - "host":{ - "name":"fake-1" + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb71f", + "index": "ml_host_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "host": { + "name": "fake-1", + "risk": { + "calculated_level": "Moderate", + "calculated_score_norm": 50, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb72f", - "index":"ml_host_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb72f", + "index": "ml_host_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "host": { + "name": "fake-2", + "risk": { + "calculated_level": "Moderate", + "calculated_score_norm": 50, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "host":{ - "name":"fake-2" - }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb73f", - "index":"ml_host_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] - }, - "host":{ - "name":"fake-3" + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb73f", + "index": "ml_host_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "host": { + "name": "fake-3", + "risk": { + "calculated_level": "Moderate", + "calculated_score_norm": 50, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", - "index":"ml_host_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", + "index": "ml_host_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "host": { + "name": "fake-4", + "risk": { + "calculated_level": "Moderate", + "calculated_score_norm": 50, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "host":{ - "name":"fake-4" - }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb75f", - "index":"ml_host_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] - }, - "host":{ - "name":"fake-5" + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb75f", + "index": "ml_host_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "host": { + "name": "fake-5", + "risk": { + "calculated_level": "Moderate", + "calculated_score_norm": 50, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", - "index":"ml_host_risk_score_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 21, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] - }, - "host":{ - "name":"siem-kibana" + "type": "doc", + "value": { + "id": "a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", + "index": "ml_host_risk_score_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "host": { + "name": "siem-kibana", + "risk": { + "calculated_level": "Low", + "calculated_score_norm": 21, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Low" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } diff --git a/x-pack/test/security_solution_cypress/es_archives/risky_hosts/mappings.json b/x-pack/test/security_solution_cypress/es_archives/risky_hosts/mappings.json index 02ceb5b5ebcccc..3e1b52cb22f5e9 100644 --- a/x-pack/test/security_solution_cypress/es_archives/risky_hosts/mappings.json +++ b/x-pack/test/security_solution_cypress/es_archives/risky_hosts/mappings.json @@ -11,27 +11,21 @@ "properties": { "name": { "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "type": "keyword" + }, + "calculated_score_norm": { + "type": "long" + } } } + } }, "ingest_timestamp": { "type": "date" - }, - "risk": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "risk_stats": { - "properties": { - "risk_score": { - "type": "long" - } - } } } }, @@ -69,35 +63,29 @@ "properties": { "name": { "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "type": "keyword" + }, + "calculated_score_norm": { + "type": "long" + } } } + } }, "ingest_timestamp": { "type": "date" - }, - "risk": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "risk_stats": { - "properties": { - "risk_score": { - "type": "long" - } - } } } }, "settings": { "index": { "lifecycle": { - "name": "ml_host_risk_score_latest_default", - "rollover_alias": "ml_host_risk_score_latest_default" + "name": "ml_host_risk_score_default", + "rollover_alias": "ml_host_risk_score_default" }, "mapping": { "total_fields": { diff --git a/x-pack/test/security_solution_cypress/es_archives/risky_users/data.json b/x-pack/test/security_solution_cypress/es_archives/risky_users/data.json index 2ea72c8604dc6f..5cb0404a9d0d51 100644 --- a/x-pack/test/security_solution_cypress/es_archives/risky_users/data.json +++ b/x-pack/test/security_solution_cypress/es_archives/risky_users/data.json @@ -1,174 +1,174 @@ { - "type":"doc", - "value":{ - "id":"a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", - "index":"ml_user_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 21, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] + "type": "doc", + "value": { + "id": "a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", + "index": "ml_user_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "user": { + "name": "user1", + "risk": { + "calculated_level": "Low", + "calculated_score_norm": 21, + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "user":{ - "name":"user1" - }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Low" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb71f", - "index":"ml_user_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] - }, - "user":{ - "name":"user2" + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb71f", + "index": "ml_user_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "user": { + "name": "user2", + "risk": { + "calculated_score_norm": 50, + "calculated_level": "Moderate", + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb72f", - "index":"ml_user_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb72f", + "index": "ml_user_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "user": { + "name": "user3", + "risk": { + "calculated_score_norm": 50, + "calculated_level": "Moderate", + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "user":{ - "name":"user3" - }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb73f", - "index":"ml_user_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] - }, - "user":{ - "name":"user4" + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb73f", + "index": "ml_user_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "user": { + "name": "user4", + "risk": { + "calculated_score_norm": 50, + "calculated_level": "Moderate", + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", - "index":"ml_user_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", + "index": "ml_user_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "user": { + "name": "user5", + "risk": { + "calculated_score_norm": 50, + "calculated_level": "Moderate", + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "user":{ - "name":"user5" - }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb75f", - "index":"ml_user_risk_score_latest_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 50, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] - }, - "user":{ - "name":"user6" + "type": "doc", + "value": { + "id": "a2cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb75f", + "index": "ml_user_risk_score_latest_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "user": { + "name": "user6", + "risk": { + "calculated_score_norm": 50, + "calculated_level": "Moderate", + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Moderate" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } } { - "type":"doc", - "value":{ - "id":"a4cf452c1e0375c3d4412cb550bd1783358468a3b3b777da4829d72c7d6fb74f", - "index":"ml_user_risk_score_default", - "source":{ - "@timestamp":"2021-03-10T14:51:05.766Z", - "risk_stats": { - "risk_score": 21, - "rule_risks": [ - { - "rule_name": "Unusual Linux Username", - "rule_risk": 42 - } - ] + "type": "doc", + "value": { + "id": "a4cf452c1e0375c3d4412cb550bd1783358468b3b3b777da4829d72c7d6fb74f", + "index": "ml_user_risk_score_default", + "source": { + "@timestamp": "2021-03-10T14:51:05.766Z", + "user": { + "name": "user1", + "risk": { + "calculated_score_norm": 21, + "calculated_level": "Low", + "rule_risks": [ + { + "rule_name": "Unusual Linux Username", + "rule_risk": 42 + } + ] + } }, - "user":{ - "name":"user7" - }, - "ingest_timestamp":"2021-03-09T18:02:08.319296053Z", - "risk":"Low" + "ingest_timestamp": "2021-03-09T18:02:08.319296053Z" } } -} +} \ No newline at end of file diff --git a/x-pack/test/security_solution_cypress/es_archives/risky_users/mappings.json b/x-pack/test/security_solution_cypress/es_archives/risky_users/mappings.json index 6e8db71b1813de..77eade9df7994c 100644 --- a/x-pack/test/security_solution_cypress/es_archives/risky_users/mappings.json +++ b/x-pack/test/security_solution_cypress/es_archives/risky_users/mappings.json @@ -11,27 +11,21 @@ "properties": { "name": { "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "type": "keyword" + }, + "calculated_score_norm": { + "type": "long" + } } } + } }, "ingest_timestamp": { "type": "date" - }, - "risk": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "risk_stats": { - "properties": { - "risk_score": { - "type": "long" - } - } } } }, @@ -69,35 +63,29 @@ "properties": { "name": { "type": "keyword" + }, + "risk": { + "properties": { + "calculated_level": { + "type": "keyword" + }, + "calculated_score_norm": { + "type": "long" + } } } + } }, "ingest_timestamp": { "type": "date" - }, - "risk": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - }, - "risk_stats": { - "properties": { - "risk_score": { - "type": "long" - } - } } } }, "settings": { "index": { "lifecycle": { - "name": "ml_user_risk_score_latest_default", - "rollover_alias": "ml_user_risk_score_latest_default" + "name": "ml_user_risk_score_default", + "rollover_alias": "ml_user_risk_score_default" }, "mapping": { "total_fields": { @@ -111,4 +99,4 @@ } } } -} +} \ No newline at end of file From 461b321e5151530a5c9e718a07d3a69d1b06ef83 Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Fri, 9 Sep 2022 14:25:45 +0200 Subject: [PATCH 006/144] [Lens] Auto open field picker within annotation panel on mount (#140315) * :alembic: Initial code for query based annotations * :bug: Solved more conflicts * :alembic: More scaffolding layout * :alembic: Initial indexpatetrn move into frame * :alembic: Make field selection work * :construction: Fixed almost all dataViews occurrencies, but changeIndexPattern * :construction: More work on change index pattern * Move lens dataViews state into main state * :fire: Remove some old cruft from the code * :bug: Fix dataViews layer change * :bug: Fix datasourceLayers refs * :fire: Remove more old cruft * :bug: Fix bug when loading SO * :bug: Fix initial existence flag * :label: Fix type issues * :label: Fix types and tests * :label: Fix types issues * :white_check_mark: Fix more tests * :white_check_mark: Fix with new dataViews structure * :white_check_mark: Fix more test mocks * :white_check_mark: More tests fixed * :fire: Removed unused prop * :white_check_mark: Down to single broken test suite * :label: Fix type issue * :ok_hand: Integrate selector feedback * :white_check_mark: Fix remaining unit tests * :label: fix type issues * :bug: Fix bug when creating dataview in place * :sparkles: Update with latest dataview state + fix dataviews picker for annotations * :bug: Fix edit + remove field flow * Update x-pack/plugins/lens/public/visualizations/xy/types.ts * :camera_flash: Fix snapshot * :bug: Fix the dataViews switch bug * :fire: remove old cruft * :recycle: Revert removal from dataviews state branch * :recycle: Load all at once * :wrench: working on persistent state + fix new layer bug * :fire: remove unused stuff * :label: Fix some typings * :wrench: Fix expression issue * :white_check_mark: Add service unit tests * :ok_hand: Integrated feedback * :sparkles: Add migration code for manual annotations * :label: Fix type issue * :white_check_mark: Add some other unit test * :label: Fix more type issues * :bug: Fix importing issue * :recycle: Make range default color dependant on opint one * :bug: Fix duplicate fields selection in tooltip section * :white_check_mark: Add more unit tests * :white_check_mark: Fix broken test * :label: Mute ts error for now * :white_check_mark: Fix tests * :fire: Reduce plugin weight * :bug: prevent layout shift on panel open * :bug: Fix extract + inject visualization references * :label: fix type issues * :sparkles: Add dataview reference migration for annotations * :wrench: Add migration to embedadble * :label: Fix type export * :bug: Fix more conflicts with main * :white_check_mark: Fix tests * :label: Make textField optional * :recycle: Refactor query input to be a shared component * :bug: Fix missing import * :bug: fix more import issues * :fire: remove duplicate code * :bug: Fix dataView switch bug * :label: Fix type issue * annotations with fetching_event_annotations * portal for kql input fix * timeField goes for default if not filled * limit changes * handle ad-hoc data view references correctly * fix types * adjust tests to datatable format (remove isHidden tests as it's filtered before) * small refactors * fix loading on dashboard * empty is invalid (?) tbd * new tooltip * emptyDatatable * :recycle: Flip field + query inputs * :label: Fix type issue * :sparkles: Add field validation for text and tooltip fields * tooltip for single annotation * fix tests * fix for non--timefilter dataview * fix annotations test - the cause was that we now don't display label for aggregated annotations ever * use eui elements * newline problem solved * :white_check_mark: Add more error tests * :ok_hand: Rename migration state version type * fix types for expression chart * :bug: Fix i18n id * :label: Fix type issue * fix hidden all annotations * :bug: Make new empty field picker auto focus by default * :white_check_mark: Fix tests after ishidden removal * :fire: Remove old cruft Co-authored-by: Joe Reuter Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Co-authored-by: Marta Bondyra --- .../annotations_config_panel/annotations_panel.tsx | 1 + .../annotations_config_panel/tooltip_annotation_panel.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx index 96f31e2e8754f0..778a1a13e200e0 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx @@ -245,6 +245,7 @@ export const AnnotationsPanel = ( } }} fieldIsInvalid={!fieldIsValid} + autoFocus={!selectedField} /> ); diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/tooltip_annotation_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/tooltip_annotation_panel.tsx index e4945f42f8089e..c8ea7a0ed2ece7 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/tooltip_annotation_panel.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/tooltip_annotation_panel.tsx @@ -198,6 +198,7 @@ export function TooltipSection({ onFieldSelectChange(choice, index); }} fieldIsInvalid={!fieldIsValid} + autoFocus={isNew && value == null} /> From 705a21f2594f94b7038227149b872b44b280ad4c Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 9 Sep 2022 06:49:41 -0600 Subject: [PATCH 007/144] [Maps] fix cluster layer disappears when switching from resolution 'high' to resolution 'low' (#140333) --- .../mvt_vector_layer/mvt_vector_layer.test.tsx | 7 ++++++- .../public/classes/layers/vector_layer/vector_layer.tsx | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.test.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.test.tsx index d61e3e46a11199..a1d29c8db13636 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.test.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.test.tsx @@ -23,7 +23,7 @@ import { TiledSingleLayerVectorSourceDescriptor, VectorLayerDescriptor, } from '../../../../../common/descriptor_types'; -import { SOURCE_TYPES } from '../../../../../common/constants'; +import { LAYER_TYPE, SOURCE_TYPES } from '../../../../../common/constants'; import { MvtVectorLayer } from './mvt_vector_layer'; const defaultConfig = { @@ -63,6 +63,11 @@ function createLayer( return new MvtVectorLayer({ layerDescriptor, source: mvtSource, customIcons: [] }); } +test('should have type MVT_VECTOR_LAYER', () => { + const layer: MvtVectorLayer = createLayer({}, {}); + expect(layer.getType()).toEqual(LAYER_TYPE.MVT_VECTOR); +}); + describe('visiblity', () => { it('should get minzoom from source', async () => { const layer: MvtVectorLayer = createLayer({}, {}); diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 3c78bf954e258b..35a5caa7ff9b8f 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -123,7 +123,8 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer { mapColors?: string[] ): VectorLayerDescriptor { const layerDescriptor = super.createDescriptor(options) as VectorLayerDescriptor; - layerDescriptor.type = LAYER_TYPE.GEOJSON_VECTOR; + layerDescriptor.type = + layerDescriptor.type !== undefined ? layerDescriptor.type : LAYER_TYPE.GEOJSON_VECTOR; if (!options.style) { const styleProperties = VectorStyle.createDefaultStyleProperties(mapColors ? mapColors : []); From 385dc10e3a790c63f9c32e67c76d52f5dfdc075a Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 9 Sep 2022 15:02:11 +0200 Subject: [PATCH 008/144] apply single fn correctly (#140381) --- .../expressions/collapse/collapse_fn.test.ts | 43 ++++++++++++++++--- .../expressions/collapse/collapse_fn.ts | 7 +-- .../lens/common/expressions/collapse/index.ts | 2 +- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.test.ts b/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.test.ts index f8786534309547..ed9f46f96b44c6 100644 --- a/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.test.ts +++ b/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.test.ts @@ -33,12 +33,45 @@ describe('collapse_fn', () => { { val: 8, split: 'B' }, ], }, - { metric: ['val'], fn: 'sum' } + { metric: ['val'], fn: ['sum'] } ); expect(result.rows).toEqual([{ val: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 }]); }); + it('can use a single function for multiple metrics', async () => { + const result = await runFn( + { + type: 'datatable', + columns: [ + { id: 'val', name: 'val', meta: { type: 'number' } }, + { id: 'val2', name: 'val2', meta: { type: 'number' } }, + { id: 'val3', name: 'val3', meta: { type: 'number' } }, + { id: 'split', name: 'split', meta: { type: 'string' } }, + ], + rows: [ + { val: 1, val2: 1, val3: 1, split: 'A' }, + { val: 2, val2: 2, val3: 2, split: 'B' }, + { val: 3, val2: 3, val3: 3, split: 'B' }, + { val: 4, val2: 4, val3: 4, split: 'A' }, + { val: 5, val2: 5, val3: 5, split: 'A' }, + { val: 6, val2: 6, val3: 6, split: 'A' }, + { val: 7, val2: 7, val3: 7, split: 'B' }, + { val: 8, val2: 22, val3: 77, split: 'B' }, + ], + }, + { metric: ['val', 'val2', 'val3'], fn: ['sum'] } + ); + + expect(result.rows).toEqual([ + { + val: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8, + val2: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 22, + val3: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 77, + }, + ]); + }); + it('can use different functions for each different metric', async () => { const result = await runFn( { @@ -114,7 +147,7 @@ describe('collapse_fn', () => { }; it('splits by a column', async () => { - const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: 'sum' }); + const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: ['sum'] }); expect(result.rows).toEqual([ { val: 1 + 4 + 6, split: 'A' }, { val: 2 + 7 + 8, split: 'B' }, @@ -123,7 +156,7 @@ describe('collapse_fn', () => { }); it('applies avg', async () => { - const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: 'avg' }); + const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: ['avg'] }); expect(result.rows).toEqual([ { val: (1 + 4 + 6) / 3, split: 'A' }, { val: (2 + 7 + 8) / 3, split: 'B' }, @@ -132,7 +165,7 @@ describe('collapse_fn', () => { }); it('applies min', async () => { - const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: 'min' }); + const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: ['min'] }); expect(result.rows).toEqual([ { val: 1, split: 'A' }, { val: 2, split: 'B' }, @@ -141,7 +174,7 @@ describe('collapse_fn', () => { }); it('applies max', async () => { - const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: 'max' }); + const result = await runFn(twoSplitTable, { metric: ['val'], by: ['split'], fn: ['max'] }); expect(result.rows).toEqual([ { val: 6, split: 'A' }, { val: 8, split: 'B' }, diff --git a/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.ts b/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.ts index 5ca2248ed1ef7a..ee3192705332d6 100644 --- a/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.ts +++ b/x-pack/plugins/lens/common/expressions/collapse/collapse_fn.ts @@ -17,11 +17,8 @@ function getValueAsNumberArray(value: unknown) { } export const collapseFn: CollapseExpressionFunction['fn'] = (input, { by, metric, fn }) => { - const collapseFunctionsByMetricIndex = Array.isArray(fn) - ? fn - : metric - ? new Array(metric.length).fill(fn) - : []; + const collapseFunctionsByMetricIndex = + fn.length > 1 ? fn : metric ? new Array(metric.length).fill(fn[0]) : []; if (metric && metric.length !== collapseFunctionsByMetricIndex.length) { throw Error(`lens_collapse - Called with ${metric.length} metrics and ${fn.length} collapse functions. diff --git a/x-pack/plugins/lens/common/expressions/collapse/index.ts b/x-pack/plugins/lens/common/expressions/collapse/index.ts index 5ea792e39cb0d9..bd8df507c95e8a 100644 --- a/x-pack/plugins/lens/common/expressions/collapse/index.ts +++ b/x-pack/plugins/lens/common/expressions/collapse/index.ts @@ -13,7 +13,7 @@ type CollapseFunction = 'sum' | 'avg' | 'min' | 'max'; export interface CollapseArgs { by?: string[]; metric?: string[]; - fn: CollapseFunction | CollapseFunction[]; + fn: CollapseFunction[]; } /** From f84444dd34e72498e4f49ad9f8f5b5de4a9b8546 Mon Sep 17 00:00:00 2001 From: Mat Schaffer Date: Fri, 9 Sep 2022 22:28:30 +0900 Subject: [PATCH 009/144] Filter out error docs from standalone cluster lists (#140102) * Attempt: Filter out error docs from standalone cluster lists Not working yet. * Remove unnecessary filter standaloneClusterFilter already had this covered, but the field wasn't mapped initially. Co-authored-by: Kevin Lacabane Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../standalone_clusters/standalone_cluster_query_filter.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugins/monitoring/server/lib/standalone_clusters/standalone_cluster_query_filter.ts b/x-pack/plugins/monitoring/server/lib/standalone_clusters/standalone_cluster_query_filter.ts index b8712704f11f9f..12d140b97e27ee 100644 --- a/x-pack/plugins/monitoring/server/lib/standalone_clusters/standalone_cluster_query_filter.ts +++ b/x-pack/plugins/monitoring/server/lib/standalone_clusters/standalone_cluster_query_filter.ts @@ -23,6 +23,11 @@ export const standaloneClusterFilter = { field: 'cluster_uuid', }, }, + { + exists: { + field: 'error', + }, + }, ], }, }, From ad250c9e30e02b32e3b2f47b7ac106df1a323687 Mon Sep 17 00:00:00 2001 From: Sean Story Date: Fri, 9 Sep 2022 08:29:12 -0500 Subject: [PATCH 010/144] add pipeline meta to connectors only (#140214) * Add connector ingest pipeline metadata * Refactor ingest pipeline defs to have non-nullable fields * make pipeline optional * Add expectation for default pipeline meta --- .../common/types/connectors.ts | 9 ++++ .../index_management/setup_indices.test.ts | 3 +- .../server/index_management/setup_indices.ts | 15 +++++++ .../lib/connectors/add_connector.test.ts | 42 +++++++++++++++++++ .../server/lib/connectors/add_connector.ts | 33 +++++++++++---- 5 files changed, 94 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/enterprise_search/common/types/connectors.ts b/x-pack/plugins/enterprise_search/common/types/connectors.ts index 26b7ef917f4353..2f5b47c824c9df 100644 --- a/x-pack/plugins/enterprise_search/common/types/connectors.ts +++ b/x-pack/plugins/enterprise_search/common/types/connectors.ts @@ -30,6 +30,14 @@ export enum SyncStatus { COMPLETED = 'completed', ERROR = 'error', } + +export interface IngestPipelineParams { + extract_binary_content: boolean; + name: string; + reduce_whitespace: boolean; + run_ml_inference: boolean; +} + export interface Connector { api_key_id: string | null; configuration: ConnectorConfiguration; @@ -42,6 +50,7 @@ export interface Connector { last_sync_status: SyncStatus | null; last_synced: string | null; name: string; + pipeline?: IngestPipelineParams | null; scheduling: { enabled: boolean; interval: string; // crontab syntax diff --git a/x-pack/plugins/enterprise_search/server/index_management/setup_indices.test.ts b/x-pack/plugins/enterprise_search/server/index_management/setup_indices.test.ts index 63b777d0dff319..59e7edf1d21d5a 100644 --- a/x-pack/plugins/enterprise_search/server/index_management/setup_indices.test.ts +++ b/x-pack/plugins/enterprise_search/server/index_management/setup_indices.test.ts @@ -7,7 +7,7 @@ import { CONNECTORS_INDEX, CONNECTORS_JOBS_INDEX, CONNECTORS_VERSION } from '..'; -import { setupConnectorsIndices } from './setup_indices'; +import { defaultConnectorsPipelineMeta, setupConnectorsIndices } from './setup_indices'; describe('Setup Indices', () => { const mockClient = { @@ -29,6 +29,7 @@ describe('Setup Indices', () => { const connectorsMappings = { _meta: { version: CONNECTORS_VERSION, + pipeline: defaultConnectorsPipelineMeta, }, properties: { api_key_id: { diff --git a/x-pack/plugins/enterprise_search/server/index_management/setup_indices.ts b/x-pack/plugins/enterprise_search/server/index_management/setup_indices.ts index 08bcdbc38c3c5b..b564d519e73f99 100644 --- a/x-pack/plugins/enterprise_search/server/index_management/setup_indices.ts +++ b/x-pack/plugins/enterprise_search/server/index_management/setup_indices.ts @@ -59,11 +59,26 @@ const defaultSettings: IndicesIndexSettings = { number_of_replicas: 0, }; +export interface DefaultConnectorsPipelineMeta { + default_extract_binary_content: boolean; + default_name: string; + default_reduce_whitespace: boolean; + default_run_ml_inference: boolean; +} + +export const defaultConnectorsPipelineMeta: DefaultConnectorsPipelineMeta = { + default_extract_binary_content: true, + default_name: 'ent-search-generic-ingestion', + default_reduce_whitespace: true, + default_run_ml_inference: false, +}; + const indices: IndexDefinition[] = [ { aliases: ['.elastic-connectors'], mappings: { _meta: { + pipeline: defaultConnectorsPipelineMeta, version: '1', }, properties: connectorMappingsProperties, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts index 42d0235cbd3a31..24b01c5e0bf035 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.test.ts @@ -34,6 +34,7 @@ describe('addConnector lib function', () => { indices: { create: jest.fn(), exists: jest.fn(), + getMapping: jest.fn(), refresh: jest.fn(), }, }, @@ -49,6 +50,22 @@ describe('addConnector lib function', () => { jest.clearAllMocks(); }); + const connectorsIndicesMapping = { + '.elastic-connectors-v1': { + mappings: { + _meta: { + pipeline: { + default_extract_binary_content: true, + default_name: 'ent-search-generic-ingestion', + default_reduce_whitespace: true, + default_run_ml_inference: false, + }, + version: '1', + }, + }, + }, + }; + it('should add connector', async () => { mockClient.asCurrentUser.index.mockImplementation(() => ({ _id: 'fakeId' })); mockClient.asCurrentUser.indices.exists.mockImplementation( @@ -56,6 +73,7 @@ describe('addConnector lib function', () => { ); (fetchConnectorByIndexName as jest.Mock).mockImplementation(() => undefined); (fetchCrawlerByIndexName as jest.Mock).mockImplementation(() => undefined); + mockClient.asCurrentUser.indices.getMapping.mockImplementation(() => connectorsIndicesMapping); await expect( addConnector(mockClient as unknown as IScopedClusterClient, { @@ -76,6 +94,12 @@ describe('addConnector lib function', () => { last_sync_status: null, last_synced: null, name: 'index_name', + pipeline: { + extract_binary_content: true, + name: 'ent-search-generic-ingestion', + reduce_whitespace: true, + run_ml_inference: false, + }, scheduling: { enabled: false, interval: '0 0 0 * * ?' }, service_type: null, status: ConnectorStatus.CREATED, @@ -97,6 +121,7 @@ describe('addConnector lib function', () => { ); (fetchConnectorByIndexName as jest.Mock).mockImplementation(() => undefined); (fetchCrawlerByIndexName as jest.Mock).mockImplementation(() => undefined); + mockClient.asCurrentUser.indices.getMapping.mockImplementation(() => connectorsIndicesMapping); await expect( addConnector(mockClient as unknown as IScopedClusterClient, { @@ -115,6 +140,7 @@ describe('addConnector lib function', () => { ); (fetchConnectorByIndexName as jest.Mock).mockImplementation(() => true); (fetchCrawlerByIndexName as jest.Mock).mockImplementation(() => undefined); + mockClient.asCurrentUser.indices.getMapping.mockImplementation(() => connectorsIndicesMapping); await expect( addConnector(mockClient as unknown as IScopedClusterClient, { @@ -133,6 +159,7 @@ describe('addConnector lib function', () => { ); (fetchConnectorByIndexName as jest.Mock).mockImplementation(() => undefined); (fetchCrawlerByIndexName as jest.Mock).mockImplementation(() => true); + mockClient.asCurrentUser.indices.getMapping.mockImplementation(() => connectorsIndicesMapping); await expect( addConnector(mockClient as unknown as IScopedClusterClient, { @@ -151,6 +178,7 @@ describe('addConnector lib function', () => { ); (fetchConnectorByIndexName as jest.Mock).mockImplementation(() => true); (fetchCrawlerByIndexName as jest.Mock).mockImplementation(() => undefined); + mockClient.asCurrentUser.indices.getMapping.mockImplementation(() => connectorsIndicesMapping); await expect( addConnector(mockClient as unknown as IScopedClusterClient, { @@ -169,6 +197,7 @@ describe('addConnector lib function', () => { ); (fetchConnectorByIndexName as jest.Mock).mockImplementation(() => ({ id: 'connectorId' })); (fetchCrawlerByIndexName as jest.Mock).mockImplementation(() => undefined); + mockClient.asCurrentUser.indices.getMapping.mockImplementation(() => connectorsIndicesMapping); await expect( addConnector(mockClient as unknown as IScopedClusterClient, { @@ -194,6 +223,12 @@ describe('addConnector lib function', () => { last_sync_status: null, last_synced: null, name: 'index_name', + pipeline: { + extract_binary_content: true, + name: 'ent-search-generic-ingestion', + reduce_whitespace: true, + run_ml_inference: false, + }, scheduling: { enabled: false, interval: '0 0 0 * * ?' }, service_type: null, status: ConnectorStatus.CREATED, @@ -218,6 +253,7 @@ describe('addConnector lib function', () => { ); (fetchConnectorByIndexName as jest.Mock).mockImplementation(() => false); (fetchCrawlerByIndexName as jest.Mock).mockImplementation(() => undefined); + mockClient.asCurrentUser.indices.getMapping.mockImplementation(() => connectorsIndicesMapping); await expect( addConnector(mockClient as unknown as IScopedClusterClient, { index_name: 'search-index_name', @@ -238,6 +274,12 @@ describe('addConnector lib function', () => { last_sync_status: null, last_synced: null, name: 'index_name', + pipeline: { + extract_binary_content: true, + name: 'ent-search-generic-ingestion', + reduce_whitespace: true, + run_ml_inference: false, + }, scheduling: { enabled: false, interval: '0 0 0 * * ?' }, service_type: null, status: ConnectorStatus.CREATED, diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts index f3275c0b2d73b6..6838ef95ce936c 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts @@ -8,9 +8,13 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CONNECTORS_INDEX } from '../..'; +import { CONNECTORS_VERSION } from '../..'; import { ConnectorDocument, ConnectorStatus } from '../../../common/types/connectors'; import { ErrorCode } from '../../../common/types/error_codes'; -import { setupConnectorsIndices } from '../../index_management/setup_indices'; +import { + DefaultConnectorsPipelineMeta, + setupConnectorsIndices, +} from '../../index_management/setup_indices'; import { fetchCrawlerByIndexName } from '../crawler/fetch_crawlers'; import { createIndex } from '../indices/create_index'; @@ -67,6 +71,19 @@ export const addConnector = async ( service_type?: string | null; } ): Promise<{ id: string; index_name: string }> => { + const connectorsIndexExists = await client.asCurrentUser.indices.exists({ + index: CONNECTORS_INDEX, + }); + if (!connectorsIndexExists) { + await setupConnectorsIndices(client.asCurrentUser); + } + const connectorsIndicesMapping = await client.asCurrentUser.indices.getMapping({ + index: CONNECTORS_INDEX, + }); + const connectorsPipelineMeta: DefaultConnectorsPipelineMeta = + connectorsIndicesMapping[`${CONNECTORS_INDEX}-v${CONNECTORS_VERSION}`]?.mappings?._meta + ?.pipeline; + const document: ConnectorDocument = { api_key_id: null, configuration: {}, @@ -78,16 +95,18 @@ export const addConnector = async ( last_sync_status: null, last_synced: null, name: input.index_name.startsWith('search-') ? input.index_name.substring(7) : input.index_name, + pipeline: connectorsPipelineMeta + ? { + extract_binary_content: connectorsPipelineMeta.default_extract_binary_content, + name: connectorsPipelineMeta.default_name, + reduce_whitespace: connectorsPipelineMeta.default_reduce_whitespace, + run_ml_inference: connectorsPipelineMeta.default_run_ml_inference, + } + : null, scheduling: { enabled: false, interval: '0 0 0 * * ?' }, service_type: input.service_type || null, status: ConnectorStatus.CREATED, sync_now: false, }; - const connectorsIndexExists = await client.asCurrentUser.indices.exists({ - index: CONNECTORS_INDEX, - }); - if (!connectorsIndexExists) { - await setupConnectorsIndices(client.asCurrentUser); - } return await createConnector(document, client, input.language, !!input.delete_existing_connector); }; From c8afa7f3a34badab5e0eababd74815c96a22602d Mon Sep 17 00:00:00 2001 From: Kristof C Date: Fri, 9 Sep 2022 08:42:55 -0500 Subject: [PATCH 011/144] Update overview page to use SecuritySolutionLinkButton (#140345) Co-authored-by: Kristof-Pierre Cummings --- .../components/overview_host/index.tsx | 39 +++++-------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx index 6e35d801c75d9d..c985d5a7af6552 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_host/index.tsx @@ -11,18 +11,17 @@ import numeral from '@elastic/numeral'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useMemo, useCallback, useState, useEffect } from 'react'; -import { DEFAULT_NUMBER_FORMAT, APP_UI_ID } from '../../../../common/constants'; +import { DEFAULT_NUMBER_FORMAT } from '../../../../common/constants'; import type { ESQuery } from '../../../../common/typed_json'; import { ID as OverviewHostQueryId, useHostOverview } from '../../containers/overview_host'; import { HeaderSection } from '../../../common/components/header_section'; -import { useUiSetting$, useKibana } from '../../../common/lib/kibana'; -import { getHostDetailsUrl, useFormatUrl } from '../../../common/components/link_to'; +import { useUiSetting$ } from '../../../common/lib/kibana'; import { getOverviewHostStats, OverviewHostStats } from '../overview_host_stats'; import { manageQuery } from '../../../common/components/page/manage_query'; import { InspectButtonContainer } from '../../../common/components/inspect'; +import { SecuritySolutionLinkButton } from '../../../common/components/links'; import type { GlobalTimeArgs } from '../../../common/containers/use_global_time'; import { SecurityPageName } from '../../../app/types'; -import { LinkButton } from '../../../common/components/links'; import { useQueryToggle } from '../../../common/containers/query_toggle'; export interface OwnProps { @@ -43,8 +42,6 @@ const OverviewHostComponent: React.FC = ({ startDate, setQuery, }) => { - const { formatUrl, search: urlSearch } = useFormatUrl(SecurityPageName.hosts); - const { navigateToApp } = useKibana().services.application; const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); const { toggleStatus, setToggleStatus } = useQueryToggle(OverviewHostQueryId); @@ -69,17 +66,6 @@ const OverviewHostComponent: React.FC = ({ skip: querySkip, }); - const goToHost = useCallback( - (ev) => { - ev.preventDefault(); - navigateToApp(APP_UI_ID, { - deepLinkId: SecurityPageName.hosts, - path: getHostDetailsUrl('allHosts', urlSearch), - }); - }, - [navigateToApp, urlSearch] - ); - const hostEventsCount = useMemo( () => getOverviewHostStats(overviewHost).reduce((total, stat) => total + stat.count, 0), [overviewHost] @@ -90,18 +76,6 @@ const OverviewHostComponent: React.FC = ({ [defaultNumberFormat, hostEventsCount] ); - const hostPageButton = useMemo( - () => ( - - - - ), - [goToHost, formatUrl] - ); - const title = useMemo( () => ( = ({ title={title} isInspectDisabled={filterQuery === undefined} > - <>{hostPageButton} + + + {toggleStatus && ( Date: Fri, 9 Sep 2022 17:00:39 +0300 Subject: [PATCH 012/144] fixes journeys that prematurely teardown before requests finish (#140383) --- .../test/performance/services/performance.ts | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/x-pack/test/performance/services/performance.ts b/x-pack/test/performance/services/performance.ts index 7f7156284d1860..ffddc834dc1157 100644 --- a/x-pack/test/performance/services/performance.ts +++ b/x-pack/test/performance/services/performance.ts @@ -8,10 +8,11 @@ /* eslint-disable no-console */ import Url from 'url'; +import * as Rx from 'rxjs'; import { inspect } from 'util'; import { setTimeout } from 'timers/promises'; import apm, { Span, Transaction } from 'elastic-apm-node'; -import playwright, { ChromiumBrowser, Page, BrowserContext, CDPSession } from 'playwright'; +import playwright, { ChromiumBrowser, Page, BrowserContext, CDPSession, Request } from 'playwright'; import { FtrService, FtrProviderContext } from '../ftr_provider_context'; export interface StepCtx { @@ -24,12 +25,16 @@ export type Steps = Array<{ name: string; handler: StepFn }>; export class PerformanceTestingService extends FtrService { private readonly auth = this.ctx.getService('auth'); + private readonly log = this.ctx.getService('log'); private readonly config = this.ctx.getService('config'); private browser: ChromiumBrowser | undefined; private currentSpanStack: Array = []; private currentTransaction: Transaction | undefined | null = undefined; + private pageTeardown$ = new Rx.Subject(); + private telemetryTrackerSubs = new Map(); + constructor(ctx: FtrProviderContext) { super(ctx); @@ -164,6 +169,44 @@ export class PerformanceTestingService extends FtrService { return client; } + private telemetryTrackerCount = 0; + + private trackTelemetryRequests(page: Page) { + const id = ++this.telemetryTrackerCount; + + const requestFailure$ = Rx.fromEvent(page, 'requestfailed'); + const requestSuccess$ = Rx.fromEvent(page, 'requestfinished'); + const request$ = Rx.fromEvent(page, 'request').pipe( + Rx.takeUntil( + this.pageTeardown$.pipe( + Rx.first((p) => p === page), + Rx.delay(3000) + // If EBT client buffers: + // Rx.mergeMap(async () => { + // await page.waitForFunction(() => { + // // return window.kibana_ebt_client.buffer_size == 0 + // }); + // }) + ) + ), + Rx.mergeMap((request) => { + if (!request.url().includes('telemetry-staging.elastic.co')) { + return Rx.EMPTY; + } + + this.log.debug(`Waiting for telemetry request #${id} to complete`); + return Rx.merge(requestFailure$, requestSuccess$).pipe( + Rx.first((r) => r === request), + Rx.tap({ + complete: () => this.log.debug(`Telemetry request #${id} complete`), + }) + ); + }) + ); + + this.telemetryTrackerSubs.set(page, request$.subscribe()); + } + private async interceptBrowserRequests(page: Page) { await page.route('**', async (route, request) => { const headers = await request.allHeaders(); @@ -196,6 +239,7 @@ export class PerformanceTestingService extends FtrService { } const client = await this.sendCDPCommands(context, page); + this.trackTelemetryRequests(page); await this.interceptBrowserRequests(page); await this.handleSteps(steps, page); await this.tearDown(page, client, context); @@ -204,6 +248,16 @@ export class PerformanceTestingService extends FtrService { private async tearDown(page: Page, client: CDPSession, context: BrowserContext) { if (page) { + const telemetryTracker = this.telemetryTrackerSubs.get(page); + this.telemetryTrackerSubs.delete(page); + + if (telemetryTracker && !telemetryTracker.closed) { + this.log.info( + `Waiting for telemetry requests to complete, including requests starting within next 3 secs` + ); + this.pageTeardown$.next(page); + await new Promise((resolve) => telemetryTracker.add(resolve)); + } await client.detach(); await page.close(); await context.close(); From b753a1a1a9f43d386876a5bcce27077559575a62 Mon Sep 17 00:00:00 2001 From: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Date: Fri, 9 Sep 2022 16:02:20 +0200 Subject: [PATCH 013/144] [Lens] Fix query input A11y bug: doesn't react to `escape` button (#140382) * [Lens] Fix query input A11y bug: doesn't react to `escape` button * only prevent default when suggestions are visible --- .../public/query_string_input/query_string_input.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/unified_search/public/query_string_input/query_string_input.tsx b/src/plugins/unified_search/public/query_string_input/query_string_input.tsx index d37c4bb72d40e9..c37e050b0823ad 100644 --- a/src/plugins/unified_search/public/query_string_input/query_string_input.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_string_input.tsx @@ -378,7 +378,9 @@ export default class QueryStringInputUI extends PureComponent { } break; case KEY_CODES.ESC: - event.preventDefault(); + if (isSuggestionsVisible) { + event.preventDefault(); + } this.setState({ isSuggestionsVisible: false, index: null }); break; case KEY_CODES.TAB: From 4f77418af4678146a90e367b9d4dda2a54665b6b Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 9 Sep 2022 16:11:43 +0200 Subject: [PATCH 014/144] add note (#140385) --- x-pack/plugins/lens/readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md index 47a1d82c36a15d..41db47090cb47d 100644 --- a/x-pack/plugins/lens/readme.md +++ b/x-pack/plugins/lens/readme.md @@ -148,6 +148,8 @@ Example: } ``` +**Important!** To prevent conflicts, it's important to not re-use ad-hoc data view ids for different specs. If you change the spec in some way, make sure to also change its id. This even applies across multiple embeddables, sessions, etc. Ideally, the id will be globally unique. You can use the `uuid` package to generate a new unique id every time when you are changing the spec in some way. However, make sure to also not change the id on every single render either, as this will have a substantial performance impact. + ## Refreshing a Lens embeddable The Lens embeddable is handling data fetching internally, this means as soon as the props change, it will trigger a new request if necessary. However, in some situations it's necessary to trigger a refresh even if the configuration of the chart doesn't change at all. Refreshing is managed using search sessions is Lens. To trigger a refresh without changing the actual configuration of a Lens embeddable, follow these steps: From 30fe5a42cd267207e0b4f0311559883b55562ac5 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Fri, 9 Sep 2022 16:14:17 +0200 Subject: [PATCH 015/144] [Security Solution][Endpoint][Response Actions] Fix displayed command on actions log (#140378) refs https://github.com/elastic/kibana/pull/134520/files#diff-8ab5fe0c53989a885ddae94fc256be8033f0252684ec7539cf1e45660e943af8R62 --- .../components/hooks.tsx | 12 ++++++++++-- .../response_actions_log.test.tsx | 2 +- .../response_actions_log.tsx | 17 ++++++++--------- .../translations/translations/fr-FR.json | 12 ++---------- .../translations/translations/ja-JP.json | 7 ------- .../translations/translations/zh-CN.json | 7 ------- 6 files changed, 21 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx index 4bf28276d16515..323c46a6cbbdaa 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx @@ -10,7 +10,10 @@ import type { DurationRange, OnRefreshChangeProps, } from '@elastic/eui/src/components/date_picker/types'; -import type { ResponseActionStatus } from '../../../../../common/endpoint/service/response_actions/constants'; +import type { + ResponseActions, + ResponseActionStatus, +} from '../../../../../common/endpoint/service/response_actions/constants'; import { RESPONSE_ACTION_COMMANDS, RESPONSE_ACTION_STATUS, @@ -111,6 +114,11 @@ export const getActionStatus = (status: ResponseActionStatus): string => { return ''; }; +export const getCommand = ( + command: ResponseActions +): Exclude | 'release' | 'processes' => + command === 'unisolate' ? 'release' : command === 'running-processes' ? 'processes' : command; + // TODO: add more filter names here export type FilterName = keyof typeof FILTER_NAMES; export const useActionsLogFilter = ( @@ -139,7 +147,7 @@ export const useActionsLogFilter = ( })) : RESPONSE_ACTION_COMMANDS.map((filter) => ({ key: filter, - label: filter === 'unisolate' ? 'release' : filter, + label: getCommand(filter), checked: undefined, })) ); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx index 1b97987d4a1313..1f5e39c532a6f4 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx @@ -488,7 +488,7 @@ describe('Response Actions Log', () => { expect(filterList.querySelectorAll('ul>li').length).toEqual(5); expect( Array.from(filterList.querySelectorAll('ul>li')).map((option) => option.textContent) - ).toEqual(['isolate', 'release', 'kill-process', 'suspend-process', 'running-processes']); + ).toEqual(['isolate', 'release', 'kill-process', 'suspend-process', 'processes']); }); it('should have `clear all` button `disabled` when no selected values', () => { diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx index 8f873da6d9232e..d12fce4efcb956 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx @@ -41,14 +41,11 @@ import { OUTPUT_MESSAGES, TABLE_COLUMN_NAMES, UX_MESSAGES } from './translations import { MANAGEMENT_PAGE_SIZE_OPTIONS } from '../../common/constants'; import { useTestIdGenerator } from '../../hooks/use_test_id_generator'; import { ActionsLogFilters } from './components/actions_log_filters'; -import { getActionStatus, useDateRangePicker } from './components/hooks'; +import { getActionStatus, getCommand, useDateRangePicker } from './components/hooks'; import { StatusBadge } from './components/status_badge'; const emptyValue = getEmptyValue(); -const getCommand = (command: ResponseActions): Exclude | 'release' => - command === 'unisolate' ? 'release' : command; - // Truncated usernames const StyledFacetButton = euiStyled(EuiFacetButton)` .euiText { @@ -300,11 +297,13 @@ export const ResponseActionsLog = memo< const command = getCommand(_command); return ( - + + {command} + ); }, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 3f545e9c87229d..baa85f6fdc93ca 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -25448,7 +25448,7 @@ "xpack.securitySolution.eventsViewer.unit": "{totalCount, plural, =1 {événement} other {événements}}", "xpack.securitySolution.exceptions.dissasociateListSuccessText": "La liste d'exceptions ({id}) a été retirée avec succès", "xpack.securitySolution.exceptions.exceptionItem.showCommentsLabel": "Afficher {comments, plural, =1 {commentaire} other {commentaires}} ({comments})", - "xpack.securitySolution.exceptions.failedLoadPolicies": "Une erreur s'est produite lors du chargement des politiques : \"{error}\"", + "xpack.securitySolution.exceptions.failedLoadPolicies": "Une erreur s'est produite lors du chargement des politiques : \"{error}\"", "xpack.securitySolution.exceptions.fetch404Error": "La liste d'exceptions associée ({listId}) n'existe plus. Veuillez retirer la liste d'exceptions manquante pour ajouter des exceptions supplémentaires à la règle de détection.", "xpack.securitySolution.exceptions.hideCommentsLabel": "Masquer ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", "xpack.securitySolution.exceptions.referenceModalDescription": "Cette liste d'exceptions est associée à ({referenceCount}) {referenceCount, plural, =1 {règle} other {règles}}. Le retrait de cette liste d'exceptions supprimera également sa référence des règles associées.", @@ -25535,7 +25535,6 @@ "xpack.securitySolution.responder.header.lastSeen": "Vu en dernier le {date}", "xpack.securitySolution.responder.hostOffline.callout.body": "L'hôte {name} est hors connexion, donc ses réponses peuvent avoir du retard. Les commandes en attente seront exécutées quand l'hôte se reconnectera.", "xpack.securitySolution.responseActionsList.flyout.title": "Log d'action : {hostname}", - "xpack.securitySolution.responseActionsList.list.item.command": "{command}", "xpack.securitySolution.responseActionsList.list.item.hasExpired": "Échec de {command} : action expirée", "xpack.securitySolution.responseActionsList.list.item.hasFailed": "Échec de {command}", "xpack.securitySolution.responseActionsList.list.item.isPending": "{command} est en attente", @@ -28022,7 +28021,6 @@ "xpack.securitySolution.exceptions.clearExceptionsLabel": "Retirer la liste d'exceptions", "xpack.securitySolution.exceptions.commentEventLabel": "a ajouté un commentaire", "xpack.securitySolution.exceptions.dissasociateExceptionListError": "Impossible de retirer la liste d'exceptions", - "xpack.securitySolution.exceptions.dissasociateListSuccessText": "La liste d'exceptions ({id}) a été retirée avec succès", "xpack.securitySolution.exceptions.editException.bulkCloseLabel": "Fermer toutes les alertes qui correspondent à cette exception et ont été générées par cette règle", "xpack.securitySolution.exceptions.editException.bulkCloseLabel.disabled": "Fermer toutes les alertes qui correspondent à cette exception et ont été générées par cette règle (les listes et les champs non ECS ne sont pas pris en charge)", "xpack.securitySolution.exceptions.editException.cancel": "Annuler", @@ -28036,11 +28034,8 @@ "xpack.securitySolution.exceptions.editException.versionConflictDescription": "Cette exception semble avoir été mise à jour depuis que vous l'avez sélectionnée pour la modifier. Essayez de cliquer sur \"Annuler\" et de modifier à nouveau l'exception.", "xpack.securitySolution.exceptions.editException.versionConflictTitle": "Désolé, une erreur est survenue", "xpack.securitySolution.exceptions.errorLabel": "Erreur", - "xpack.securitySolution.exceptions.failedLoadPolicies": "Une erreur s'est produite lors du chargement des politiques : \"{error}\"", - "xpack.securitySolution.exceptions.fetch404Error": "La liste d'exceptions associée ({listId}) n'existe plus. Veuillez retirer la liste d'exceptions manquante pour ajouter des exceptions supplémentaires à la règle de détection.", "xpack.securitySolution.exceptions.fetchError": "Erreur lors de la récupération de la liste d'exceptions", - "xpack.securitySolution.exceptions.hideCommentsLabel": "Masquer ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", - "xpack.securitySolution.exceptions.modalErrorAccordionText": "Afficher les informations de référence de la règle :", + "xpack.securitySolution.exceptions.modalErrorAccordionText": "Afficher les informations de référence de la règle :", "xpack.securitySolution.exceptions.exceptionItem.conditions.and": "AND", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator": "existe", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator.not": "n'existe pas", @@ -28062,8 +28057,6 @@ "xpack.securitySolution.exceptions.exceptionItem.editItemButton": "Modifier l’élément", "xpack.securitySolution.exceptions.exceptionItem.metaDetailsBy": "par", "xpack.securitySolution.exceptions.exceptionItem.updatedLabel": "Mis à jour", - "xpack.securitySolution.exceptions.fetchError": "Erreur lors de la récupération de la liste d'exceptions", - "xpack.securitySolution.exceptions.modalErrorAccordionText": "Afficher les informations de référence de la règle :", "xpack.securitySolution.exceptions.operatingSystemFullLabel": "Système d'exploitation", "xpack.securitySolution.exceptions.operatingSystemLinux": "Linux", "xpack.securitySolution.exceptions.operatingSystemMac": "macOS", @@ -28073,7 +28066,6 @@ "xpack.securitySolution.exceptions.referenceModalDeleteButton": "Retirer la liste d'exceptions", "xpack.securitySolution.exceptions.referenceModalTitle": "Retirer la liste d'exceptions", "xpack.securitySolution.exceptions.searchPlaceholder": "par ex. Exemple de liste de noms", - "xpack.securitySolution.exceptions.showCommentsLabel": "Afficher ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "Ajouter un nouveau commentaire...", "xpack.securitySolution.exceptions.viewer.addToClipboard": "Commentaire", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "Ajouter une exception à une règle", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 75b6e829bd3e77..703ecc49772eeb 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25512,7 +25512,6 @@ "xpack.securitySolution.responder.header.lastSeen": "前回表示日時 {date}", "xpack.securitySolution.responder.hostOffline.callout.body": "ホスト{name}はオフラインであるため、応答が遅延する可能性があります。保留中のコマンドは、ホストが再接続されたときに実行されます。", "xpack.securitySolution.responseActionsList.flyout.title": "アクションログ:{hostname}", - "xpack.securitySolution.responseActionsList.list.item.command": "{command}", "xpack.securitySolution.responseActionsList.list.item.hasExpired": "{command}が失敗しました:アクションの有効期限が切れました", "xpack.securitySolution.responseActionsList.list.item.hasFailed": "{command}が失敗しました", "xpack.securitySolution.responseActionsList.list.item.isPending": "{command}は保留中です", @@ -27999,7 +27998,6 @@ "xpack.securitySolution.exceptions.clearExceptionsLabel": "例外リストを削除", "xpack.securitySolution.exceptions.commentEventLabel": "コメントを追加しました", "xpack.securitySolution.exceptions.dissasociateExceptionListError": "例外リストを削除できませんでした", - "xpack.securitySolution.exceptions.dissasociateListSuccessText": "例外リスト({id})が正常に削除されました", "xpack.securitySolution.exceptions.editException.bulkCloseLabel": "この例外一致し、このルールによって生成された、すべてのアラートを閉じる", "xpack.securitySolution.exceptions.editException.bulkCloseLabel.disabled": "この例外と一致し、このルールによって生成された、すべてのアラートを閉じる(リストと非ECSフィールドはサポートされません)", "xpack.securitySolution.exceptions.editException.cancel": "キャンセル", @@ -28013,10 +28011,7 @@ "xpack.securitySolution.exceptions.editException.versionConflictDescription": "最初に編集することを選択したときからこの例外が更新されている可能性があります。[キャンセル]をクリックし、もう一度例外を編集してください。", "xpack.securitySolution.exceptions.editException.versionConflictTitle": "申し訳ございません、エラーが発生しました", "xpack.securitySolution.exceptions.errorLabel": "エラー", - "xpack.securitySolution.exceptions.failedLoadPolicies": "ポリシーの読み込みエラーが発生しました:\"{error}\"", - "xpack.securitySolution.exceptions.fetch404Error": "関連付けられた例外リスト({listId})は存在しません。その他の例外を検出ルールに追加するには、見つからない例外リストを削除してください。", "xpack.securitySolution.exceptions.fetchError": "例外リストの取得エラー", - "xpack.securitySolution.exceptions.hideCommentsLabel": "({comments}){comments, plural, other {件のコメント}}を非表示", "xpack.securitySolution.exceptions.exceptionItem.conditions.and": "AND", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator": "存在する", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator.not": "存在しない", @@ -28038,7 +28033,6 @@ "xpack.securitySolution.exceptions.exceptionItem.editItemButton": "項目を編集", "xpack.securitySolution.exceptions.exceptionItem.metaDetailsBy": "グループ基準", "xpack.securitySolution.exceptions.exceptionItem.updatedLabel": "更新しました", - "xpack.securitySolution.exceptions.fetchError": "例外リストの取得エラー", "xpack.securitySolution.exceptions.modalErrorAccordionText": "ルール参照情報を表示:", "xpack.securitySolution.exceptions.operatingSystemFullLabel": "オペレーティングシステム", "xpack.securitySolution.exceptions.operatingSystemLinux": "Linux", @@ -28049,7 +28043,6 @@ "xpack.securitySolution.exceptions.referenceModalDeleteButton": "例外リストを削除", "xpack.securitySolution.exceptions.referenceModalTitle": "例外リストを削除", "xpack.securitySolution.exceptions.searchPlaceholder": "例:例外リスト名", - "xpack.securitySolution.exceptions.showCommentsLabel": "({comments}){comments, plural, other {件のコメント}}を表示", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "新しいコメントを追加...", "xpack.securitySolution.exceptions.viewer.addToClipboard": "コメント", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "ルール例外の追加", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a1246cc1fa749b..d9f2bb79ffb9ce 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25543,7 +25543,6 @@ "xpack.securitySolution.responder.header.lastSeen": "最后看到时间 {date}", "xpack.securitySolution.responder.hostOffline.callout.body": "主机 {name} 脱机,因此其响应可能会延迟。主机重新建立连接后将执行待处理的命令。", "xpack.securitySolution.responseActionsList.flyout.title": "操作日志:{hostname}", - "xpack.securitySolution.responseActionsList.list.item.command": "{command}", "xpack.securitySolution.responseActionsList.list.item.hasExpired": "{command} 失败:操作已过期", "xpack.securitySolution.responseActionsList.list.item.hasFailed": "{command} 失败", "xpack.securitySolution.responseActionsList.list.item.isPending": "{command} 待处理", @@ -28030,7 +28029,6 @@ "xpack.securitySolution.exceptions.clearExceptionsLabel": "移除例外列表", "xpack.securitySolution.exceptions.commentEventLabel": "已添加注释", "xpack.securitySolution.exceptions.dissasociateExceptionListError": "无法移除例外列表", - "xpack.securitySolution.exceptions.dissasociateListSuccessText": "例外列表 ({id}) 已成功移除", "xpack.securitySolution.exceptions.editException.bulkCloseLabel": "关闭所有与此例外匹配且根据此规则生成的告警", "xpack.securitySolution.exceptions.editException.bulkCloseLabel.disabled": "关闭所有与此例外匹配且根据此规则生成的告警(不支持列表和非 ECS 字段)", "xpack.securitySolution.exceptions.editException.cancel": "取消", @@ -28044,10 +28042,7 @@ "xpack.securitySolution.exceptions.editException.versionConflictDescription": "此例外可能自您首次选择编辑后已更新。尝试单击“取消”,重新编辑该例外。", "xpack.securitySolution.exceptions.editException.versionConflictTitle": "抱歉,有错误", "xpack.securitySolution.exceptions.errorLabel": "错误", - "xpack.securitySolution.exceptions.failedLoadPolicies": "加载策略时出错:“{error}”", - "xpack.securitySolution.exceptions.fetch404Error": "关联的例外列表 ({listId}) 已不存在。请移除缺少的例外列表,以将其他例外添加到检测规则。", "xpack.securitySolution.exceptions.fetchError": "提取例外列表时出错", - "xpack.securitySolution.exceptions.hideCommentsLabel": "隐藏 ({comments}) 个{comments, plural, other {注释}}", "xpack.securitySolution.exceptions.exceptionItem.conditions.and": "且", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator": "存在", "xpack.securitySolution.exceptions.exceptionItem.conditions.existsOperator.not": "不存在", @@ -28069,7 +28064,6 @@ "xpack.securitySolution.exceptions.exceptionItem.editItemButton": "编辑项目", "xpack.securitySolution.exceptions.exceptionItem.metaDetailsBy": "依据", "xpack.securitySolution.exceptions.exceptionItem.updatedLabel": "已更新", - "xpack.securitySolution.exceptions.fetchError": "提取例外列表时出错", "xpack.securitySolution.exceptions.modalErrorAccordionText": "显示规则引用信息:", "xpack.securitySolution.exceptions.operatingSystemFullLabel": "操作系统", "xpack.securitySolution.exceptions.operatingSystemLinux": "Linux", @@ -28080,7 +28074,6 @@ "xpack.securitySolution.exceptions.referenceModalDeleteButton": "移除例外列表", "xpack.securitySolution.exceptions.referenceModalTitle": "移除例外列表", "xpack.securitySolution.exceptions.searchPlaceholder": "例如,示例列表名称", - "xpack.securitySolution.exceptions.showCommentsLabel": "显示 ({comments} 个) {comments, plural, other {注释}}", "xpack.securitySolution.exceptions.viewer.addCommentPlaceholder": "添加新注释......", "xpack.securitySolution.exceptions.viewer.addToClipboard": "注释", "xpack.securitySolution.exceptions.viewer.addToDetectionsListLabel": "添加规则例外", From cfff4c102ce202dcacb48a34d0abbcd60c63cc10 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Fri, 9 Sep 2022 16:14:37 +0200 Subject: [PATCH 016/144] =?UTF-8?q?Upgrade=20`node-sass`=20dependency=20(`?= =?UTF-8?q?7.0.1`=20=E2=86=92=20`7.0.3`).=20(#140366)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- yarn.lock | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index ae40de1b204f41..b223da37daa068 100644 --- a/package.json +++ b/package.json @@ -1313,7 +1313,7 @@ "ms-chromium-edge-driver": "^0.5.1", "mutation-observer": "^1.0.3", "nock": "12.0.3", - "node-sass": "7.0.1", + "node-sass": "^7.0.3", "null-loader": "^3.0.0", "nyc": "^15.1.0", "oboe": "^2.1.4", diff --git a/yarn.lock b/yarn.lock index 40141be799b42f..e0a3b8f3a5627b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18686,7 +18686,7 @@ jquery@^3.5.0: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== -js-base64@^2.4.3: +js-base64@^2.4.9: version "2.5.2" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.2.tgz#313b6274dda718f714d00b3330bbae6e38e90209" integrity sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ== @@ -20925,10 +20925,10 @@ node-releases@^2.0.5: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== -node-sass@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-7.0.1.tgz#ad4f6bc663de8acc0a9360db39165a1e2620aa72" - integrity sha512-uMy+Xt29NlqKCFdFRZyXKOTqGt+QaKHexv9STj2WeLottnlqZEEWx6Bj0MXNthmFRRdM/YwyNo/8Tr46TOM0jQ== +node-sass@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-7.0.3.tgz#7620bcd5559c2bf125c4fbb9087ba75cd2df2ab2" + integrity sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw== dependencies: async-foreach "^0.1.3" chalk "^4.1.2" @@ -20942,7 +20942,7 @@ node-sass@7.0.1: node-gyp "^8.4.1" npmlog "^5.0.0" request "^2.88.0" - sass-graph "4.0.0" + sass-graph "^4.0.1" stdout-stream "^1.4.0" "true-case-path" "^1.0.2" @@ -24890,14 +24890,14 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sass-graph@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-4.0.0.tgz#fff8359efc77b31213056dfd251d05dadc74c613" - integrity sha512-WSO/MfXqKH7/TS8RdkCX3lVkPFQzCgbqdGsmSKq6tlPU+GpGEsa/5aW18JqItnqh+lPtcjifqdZ/VmiILkKckQ== +sass-graph@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-4.0.1.tgz#2ff8ca477224d694055bf4093f414cf6cfad1d2e" + integrity sha512-5YCfmGBmxoIRYHnKK2AKzrAkCoQ8ozO+iumT8K4tXJXRVCPf+7s1/9KxTSW3Rbvf+7Y7b4FR3mWyLnQr3PHocA== dependencies: glob "^7.0.0" lodash "^4.17.11" - scss-tokenizer "^0.3.0" + scss-tokenizer "^0.4.3" yargs "^17.2.1" sass-loader@^10.3.1: @@ -25007,13 +25007,13 @@ screenfull@^5.0.0: resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.0.0.tgz#5c2010c0e84fd4157bf852877698f90b8cbe96f6" integrity sha512-yShzhaIoE9OtOhWVyBBffA6V98CDCoyHTsp8228blmqYy1Z5bddzE/4FPiJKlr8DVR4VBiiUyfPzIQPIYDkeMA== -scss-tokenizer@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.3.0.tgz#ef7edc3bc438b25cd6ffacf1aa5b9ad5813bf260" - integrity sha512-14Zl9GcbBvOT9057ZKjpz5yPOyUWG2ojd9D5io28wHRYsOrs7U95Q+KNL87+32p8rc+LvDpbu/i9ZYjM9Q+FsQ== +scss-tokenizer@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.4.3.tgz#1058400ee7d814d71049c29923d2b25e61dc026c" + integrity sha512-raKLgf1LI5QMQnG+RxHz6oK0sL3x3I4FN2UDLqgLOGO8hodECNnNh5BXn7fAyBxrA8zVzdQizQ6XjNJQ+uBwMw== dependencies: - js-base64 "^2.4.3" - source-map "^0.7.1" + js-base64 "^2.4.9" + source-map "^0.7.3" secure-json-parse@^2.4.0: version "2.4.0" @@ -25613,7 +25613,7 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.1, source-map@^0.7.3: +source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== From 245036bb9758c1f42814da59c82f0666a68fb42b Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 9 Sep 2022 16:46:47 +0200 Subject: [PATCH 017/144] add x-content-type-options: nosniff and a test (#140404) --- x-pack/plugins/files/server/routes/common.test.ts | 1 + x-pack/plugins/files/server/routes/common.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/x-pack/plugins/files/server/routes/common.test.ts b/x-pack/plugins/files/server/routes/common.test.ts index a8a1a5403c8914..2c4d302d04625a 100644 --- a/x-pack/plugins/files/server/routes/common.test.ts +++ b/x-pack/plugins/files/server/routes/common.test.ts @@ -20,6 +20,7 @@ describe('getDownloadHeadersForFile', () => { 'content-type': contentType, 'content-disposition': `attachment; filename="${contentDisposition}"`, 'cache-control': 'max-age=31536000, immutable', + 'x-content-type-options': 'nosniff', }; } diff --git a/x-pack/plugins/files/server/routes/common.ts b/x-pack/plugins/files/server/routes/common.ts index 8bfc7753efe3f4..0730a6435de028 100644 --- a/x-pack/plugins/files/server/routes/common.ts +++ b/x-pack/plugins/files/server/routes/common.ts @@ -15,6 +15,8 @@ export function getDownloadHeadersForFile(file: File, fileName?: string): Respon // Note, this name can be overridden by the client if set via a "download" attribute on the HTML tag. 'content-disposition': `attachment; filename="${fileName || getDownloadedFileName(file)}"`, 'cache-control': 'max-age=31536000, immutable', + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options + 'x-content-type-options': 'nosniff', }; } From b3e01c6016cfa73c2248341141260c2e4abdea4d Mon Sep 17 00:00:00 2001 From: liza-mae Date: Fri, 9 Sep 2022 09:09:24 -0600 Subject: [PATCH 018/144] Fix ML stale element failure (#140326) --- x-pack/test/functional/services/ml/trained_models_table.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/services/ml/trained_models_table.ts b/x-pack/test/functional/services/ml/trained_models_table.ts index 03b0d961e1d4cf..c8d43207dd5ab9 100644 --- a/x-pack/test/functional/services/ml/trained_models_table.ts +++ b/x-pack/test/functional/services/ml/trained_models_table.ts @@ -284,7 +284,7 @@ export function TrainedModelsTableProvider( } public async openStartDeploymentModal(modelId: string) { - await testSubjects.clickWhenNotDisabledWithoutRetry( + await testSubjects.clickWhenNotDisabled( this.rowSelector(modelId, 'mlModelsTableRowStartDeploymentAction'), { timeout: 5000 } ); @@ -292,7 +292,7 @@ export function TrainedModelsTableProvider( } public async clickStopDeploymentAction(modelId: string) { - await testSubjects.clickWhenNotDisabledWithoutRetry( + await testSubjects.clickWhenNotDisabled( this.rowSelector(modelId, 'mlModelsTableRowStopDeploymentAction'), { timeout: 5000 } ); From eb33c82f4340608ff218b2aea8b1930589780284 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Fri, 9 Sep 2022 17:15:09 +0200 Subject: [PATCH 019/144] Delete host risk card from overview page (#140177) * Delete host risk card from the overview page --- .../security_solution/common/constants.ts | 3 + .../overview/risky_hosts_panel.spec.ts | 80 --------- .../cypress/screens/overview.ts | 15 -- .../cti_details/host_risk_summary.tsx | 2 +- .../host_risk_information/index.tsx | 3 +- .../hosts/components/kpi_hosts/index.tsx | 2 +- .../link_panel/inner_link_panel.tsx | 4 +- .../components/link_panel/translations.ts | 15 ++ .../threat_intel_panel_view.tsx | 3 +- .../overview_cti_links/translations.ts | 4 + .../overview_risky_host_links/index.test.tsx | 112 ------------- .../overview_risky_host_links/index.tsx | 53 ------ .../navigate_to_host.tsx | 43 ----- .../risky_hosts_disabled_module.test.tsx | 54 ------ .../risky_hosts_disabled_module.tsx | 51 ------ .../risky_hosts_enabled_module.test.tsx | 82 --------- .../risky_hosts_enabled_module.tsx | 43 ----- .../risky_hosts_panel_view.test.tsx | 67 -------- .../risky_hosts_panel_view.tsx | 157 ------------------ .../overview_risky_host_links/translations.ts | 72 -------- .../use_risky_hosts_dashboard_id.ts | 41 ----- .../use_risky_hosts_dashboard_links.tsx | 73 -------- .../public/overview/pages/overview.tsx | 20 --- .../translations/translations/fr-FR.json | 11 -- .../translations/translations/ja-JP.json | 11 -- .../translations/translations/zh-CN.json | 11 -- 26 files changed, 28 insertions(+), 1004 deletions(-) delete mode 100644 x-pack/plugins/security_solution/cypress/integration/overview/risky_hosts_panel.spec.ts create mode 100644 x-pack/plugins/security_solution/public/overview/components/link_panel/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/navigate_to_host.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_id.ts delete mode 100644 x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_links.tsx diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 6f3958cbb54e1b..a59f57e45cdd0b 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -458,3 +458,6 @@ export enum BulkActionsDryRunErrCode { MACHINE_LEARNING_AUTH = 'MACHINE_LEARNING_AUTH', MACHINE_LEARNING_INDEX_PATTERN = 'MACHINE_LEARNING_INDEX_PATTERN', } + +export const RISKY_HOSTS_DOC_LINK = + 'https://www.github.com/elastic/detection-rules/blob/main/docs/experimental-machine-learning/host-risk-score.md'; diff --git a/x-pack/plugins/security_solution/cypress/integration/overview/risky_hosts_panel.spec.ts b/x-pack/plugins/security_solution/cypress/integration/overview/risky_hosts_panel.spec.ts deleted file mode 100644 index 686acd5fd048cf..00000000000000 --- a/x-pack/plugins/security_solution/cypress/integration/overview/risky_hosts_panel.spec.ts +++ /dev/null @@ -1,80 +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 { - OVERVIEW_RISKY_HOSTS_ENABLE_MODULE_BUTTON, - OVERVIEW_RISKY_HOSTS_LINKS, - OVERVIEW_RISKY_HOSTS_LINKS_ERROR_INNER_PANEL, - OVERVIEW_RISKY_HOSTS_LINKS_WARNING_INNER_PANEL, - OVERVIEW_RISKY_HOSTS_TOTAL_EVENT_COUNT, - OVERVIEW_RISKY_HOSTS_DOC_LINK, - OVERVIEW_RISKY_HOSTS_IMPORT_DASHBOARD_BUTTON, -} from '../../screens/overview'; - -import { login, visit } from '../../tasks/login'; -import { OVERVIEW_URL } from '../../urls/navigation'; -import { cleanKibana } from '../../tasks/common'; -import { changeSpace } from '../../tasks/kibana_navigation'; -import { createSpace, removeSpace } from '../../tasks/api_calls/spaces'; -import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver'; - -const testSpaceName = 'test'; - -describe('Risky Hosts Link Panel', () => { - before(() => { - cleanKibana(); - login(); - }); - - it('renders disabled panel view as expected', () => { - visit(OVERVIEW_URL); - cy.get(`${OVERVIEW_RISKY_HOSTS_LINKS} ${OVERVIEW_RISKY_HOSTS_LINKS_ERROR_INNER_PANEL}`).should( - 'exist' - ); - cy.get(`${OVERVIEW_RISKY_HOSTS_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 0 hosts'); - cy.get(`${OVERVIEW_RISKY_HOSTS_ENABLE_MODULE_BUTTON}`).should('exist'); - cy.get(`${OVERVIEW_RISKY_HOSTS_DOC_LINK}`) - .should('have.attr', 'href') - .and('match', /host-risk-score.md/); - }); - - describe('enabled module', () => { - before(() => { - esArchiverLoad('risky_hosts'); - createSpace(testSpaceName); - }); - - after(() => { - esArchiverUnload('risky_hosts'); - removeSpace(testSpaceName); - }); - - it('renders disabled dashboard module as expected when there are no hosts in the selected time period', () => { - visit( - `${OVERVIEW_URL}?sourcerer=(timerange:(from:%272021-07-08T04:00:00.000Z%27,kind:absolute,to:%272021-07-09T03:59:59.999Z%27))` - ); - cy.get( - `${OVERVIEW_RISKY_HOSTS_LINKS} ${OVERVIEW_RISKY_HOSTS_LINKS_WARNING_INNER_PANEL}` - ).should('exist'); - cy.get(`${OVERVIEW_RISKY_HOSTS_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 0 hosts'); - }); - - it('renders space aware dashboard module as expected when there are hosts in the selected time period', () => { - visit(OVERVIEW_URL); - cy.get( - `${OVERVIEW_RISKY_HOSTS_LINKS} ${OVERVIEW_RISKY_HOSTS_LINKS_WARNING_INNER_PANEL}` - ).should('not.exist'); - cy.get(`${OVERVIEW_RISKY_HOSTS_IMPORT_DASHBOARD_BUTTON}`).should('exist'); - cy.get(`${OVERVIEW_RISKY_HOSTS_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 6 hosts'); - - changeSpace(testSpaceName); - cy.visit(`/s/${testSpaceName}${OVERVIEW_URL}`); - cy.get(`${OVERVIEW_RISKY_HOSTS_TOTAL_EVENT_COUNT}`).should('have.text', 'Showing: 0 hosts'); - cy.get(`${OVERVIEW_RISKY_HOSTS_ENABLE_MODULE_BUTTON}`).should('exist'); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/cypress/screens/overview.ts b/x-pack/plugins/security_solution/cypress/screens/overview.ts index 1e91e4fe462b95..14bfce599dfaf5 100644 --- a/x-pack/plugins/security_solution/cypress/screens/overview.ts +++ b/x-pack/plugins/security_solution/cypress/screens/overview.ts @@ -151,19 +151,4 @@ export const OVERVIEW_CTI_LINKS_ERROR_INNER_PANEL = '[data-test-subj="cti-inner- export const OVERVIEW_CTI_TOTAL_EVENT_COUNT = `${OVERVIEW_CTI_LINKS} [data-test-subj="header-panel-subtitle"]`; export const OVERVIEW_CTI_ENABLE_MODULE_BUTTON = '[data-test-subj="cti-enable-module-button"]'; -export const OVERVIEW_RISKY_HOSTS_LINKS = '[data-test-subj="risky-hosts-dashboard-links"]'; -export const OVERVIEW_RISKY_HOSTS_LINKS_ERROR_INNER_PANEL = - '[data-test-subj="risky-hosts-inner-panel-danger"]'; -export const OVERVIEW_RISKY_HOSTS_LINKS_WARNING_INNER_PANEL = - '[data-test-subj="risky-hosts-inner-panel-warning"]'; -export const OVERVIEW_RISKY_HOSTS_VIEW_DASHBOARD_BUTTON = - '[data-test-subj="risky-hosts-view-dashboard-button"]'; -export const OVERVIEW_RISKY_HOSTS_IMPORT_DASHBOARD_BUTTON = - '[data-test-subj="create-saved-object-button"]'; -export const OVERVIEW_RISKY_HOSTS_DOC_LINK = - '[data-test-subj="risky-hosts-inner-panel-danger-learn-more"]'; -export const OVERVIEW_RISKY_HOSTS_TOTAL_EVENT_COUNT = `${OVERVIEW_RISKY_HOSTS_LINKS} [data-test-subj="header-panel-subtitle"]`; -export const OVERVIEW_RISKY_HOSTS_ENABLE_MODULE_BUTTON = - '[data-test-subj="disabled-open-in-console-button-with-tooltip"]'; - export const OVERVIEW_ALERTS_HISTOGRAM = '[data-test-subj="alerts-histogram-panel"]'; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx index 9f425da6475d77..970656933b938c 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/cti_details/host_risk_summary.tsx @@ -9,10 +9,10 @@ import React from 'react'; import { EuiLoadingSpinner, EuiPanel, EuiSpacer, EuiLink, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import * as i18n from './translations'; -import { RISKY_HOSTS_DOC_LINK } from '../../../../overview/components/overview_risky_host_links/risky_hosts_disabled_module'; import { EnrichedDataRow, ThreatSummaryPanelHeader } from './threat_summary_view'; import { RiskScore } from '../../severity/common'; import type { HostRisk } from '../../../../risk_score/containers'; +import { RISKY_HOSTS_DOC_LINK } from '../../../../../common/constants'; const HostRiskSummaryComponent: React.FC<{ hostRisk: HostRisk; diff --git a/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx index 11d3575a27567e..ea1ecf8c9d6524 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/host_risk_information/index.tsx @@ -27,12 +27,11 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; -import { RISKY_HOSTS_DOC_LINK } from '../../../overview/components/overview_risky_host_links/risky_hosts_disabled_module'; - import * as i18n from './translations'; import { useOnOpenCloseHandler } from '../../../helper_hooks'; import { RiskScore } from '../../../common/components/severity/common'; import { RiskSeverity } from '../../../../common/search_strategy'; +import { RISKY_HOSTS_DOC_LINK } from '../../../../common/constants'; const tableColumns: Array> = [ { diff --git a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx index 7c73cb4f245086..f7c9352f3a9512 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/kpi_hosts/index.tsx @@ -12,9 +12,9 @@ import { HostsKpiHosts } from './hosts'; import { HostsKpiUniqueIps } from './unique_ips'; import type { HostsKpiProps } from './types'; import { CallOutSwitcher } from '../../../common/components/callouts'; -import { RISKY_HOSTS_DOC_LINK } from '../../../overview/components/overview_risky_host_links/risky_hosts_disabled_module'; import * as i18n from './translations'; import { useHostRiskScore } from '../../../risk_score/containers'; +import { RISKY_HOSTS_DOC_LINK } from '../../../../common/constants'; export const HostsKpiComponent = React.memo( ({ filterQuery, from, indexNames, to, setQuery, skip, updateDateRange }) => { diff --git a/x-pack/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx b/x-pack/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx index c4f234b43efd0f..f76b446ac72e81 100644 --- a/x-pack/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/link_panel/inner_link_panel.tsx @@ -8,7 +8,7 @@ import React from 'react'; import styled from 'styled-components'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLink, EuiSplitPanel, EuiText } from '@elastic/eui'; -import { LEARN_MORE } from '../overview_risky_host_links/translations'; +import * as i18n from './translations'; const ButtonContainer = styled(EuiFlexGroup)` padding: ${({ theme }) => theme.eui.euiSizeS}; @@ -66,7 +66,7 @@ export const InnerLinkPanel = ({ data-test-subj={`${dataTestSubj}-learn-more`} external > - {LEARN_MORE} + {i18n.LEARN_MORE} )}

diff --git a/x-pack/plugins/security_solution/public/overview/components/link_panel/translations.ts b/x-pack/plugins/security_solution/public/overview/components/link_panel/translations.ts new file mode 100644 index 00000000000000..edbfa06477ba5a --- /dev/null +++ b/x-pack/plugins/security_solution/public/overview/components/link_panel/translations.ts @@ -0,0 +1,15 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const LEARN_MORE = i18n.translate( + 'xpack.securitySolution.overview.linkPanelLearnMoreButton', + { + defaultMessage: 'Learn More', + } +); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx index 371f9a1e79f20e..c6a623f19681fb 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx @@ -16,7 +16,6 @@ import type { LinkPanelViewProps } from '../link_panel/types'; import { shortenCountIntoString } from '../../../common/utils/shorten_count_into_string'; import { Link } from '../link_panel/link'; import { ID as CTIEventCountQueryId } from '../../containers/overview_cti_links/use_ti_data_sources'; -import { LINK_COPY } from '../overview_risky_host_links/translations'; const columns: Array> = [ { name: 'Name', field: 'title', sortable: true, truncateText: true, width: '100%' }, @@ -34,7 +33,7 @@ const columns: Array> = [ field: 'path', truncateText: true, width: '80px', - render: (path: string) => , + render: (path: string) => , }, ]; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/translations.ts b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/translations.ts index 775dab6721da12..ef7f1f6540ee50 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/translations.ts +++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/translations.ts @@ -42,3 +42,7 @@ export const OTHER_DATA_SOURCE_TITLE = i18n.translate( defaultMessage: 'Others', } ); + +export const LINK_COPY = i18n.translate('xpack.securitySolution.overview.ctiLinkSource', { + defaultMessage: 'Source', +}); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.test.tsx deleted file mode 100644 index b0c5f8bc7cff96..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.test.tsx +++ /dev/null @@ -1,112 +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 React from 'react'; -import { Provider } from 'react-redux'; -import { cloneDeep } from 'lodash/fp'; -import { render, screen } from '@testing-library/react'; -import { I18nProvider } from '@kbn/i18n-react'; -import { ThemeProvider } from 'styled-components'; -import { mockTheme } from '../overview_cti_links/mock'; -import { RiskyHostLinks } from '.'; -import type { State } from '../../../common/store'; -import { createStore } from '../../../common/store'; -import { - createSecuritySolutionStorageMock, - kibanaObservable, - mockGlobalState, - SUB_PLUGINS_REDUCER, -} from '../../../common/mock'; - -import { useRiskyHostsDashboardLinks } from '../../containers/overview_risky_host_links/use_risky_hosts_dashboard_links'; -import { useHostRiskScore } from '../../../risk_score/containers'; -import { useDashboardButtonHref } from '../../../common/hooks/use_dashboard_button_href'; - -jest.mock('../../../common/lib/kibana'); - -jest.mock('../../../risk_score/containers'); -const useHostRiskScoreMock = useHostRiskScore as jest.Mock; - -jest.mock('../../../common/hooks/use_dashboard_button_href'); -const useRiskyHostsDashboardButtonHrefMock = useDashboardButtonHref as jest.Mock; -useRiskyHostsDashboardButtonHrefMock.mockReturnValue({ buttonHref: '/test' }); - -jest.mock('../../containers/overview_risky_host_links/use_risky_hosts_dashboard_links'); -const useRiskyHostsDashboardLinksMock = useRiskyHostsDashboardLinks as jest.Mock; -useRiskyHostsDashboardLinksMock.mockReturnValue({ - listItemsWithLinks: [{ title: 'a', count: 1, path: '/test' }], -}); - -describe('RiskyHostLinks', () => { - const state: State = mockGlobalState; - - const { storage } = createSecuritySolutionStorageMock(); - let store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - - beforeEach(() => { - const myState = cloneDeep(state); - store = createStore(myState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - }); - - it('renders enabled module view if module is enabled', () => { - useHostRiskScoreMock.mockReturnValueOnce([ - false, - { - data: [], - isModuleEnabled: true, - }, - ]); - - render( - - - - - - - - ); - - expect(screen.queryByTestId('risky-hosts-enable-module-button')).not.toBeInTheDocument(); - }); - - it('renders disabled module view if module is disabled', () => { - useHostRiskScoreMock.mockReturnValueOnce([ - false, - { - data: [], - isModuleEnabled: false, - }, - ]); - - render( - - - - - - - - ); - - expect(screen.getByTestId('disabled-open-in-console-button-with-tooltip')).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.tsx deleted file mode 100644 index df6286647e82ee..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/index.tsx +++ /dev/null @@ -1,53 +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 React from 'react'; - -import { RiskyHostsEnabledModule } from './risky_hosts_enabled_module'; -import { RiskyHostsDisabledModule } from './risky_hosts_disabled_module'; -import { useQueryInspector } from '../../../common/components/page/manage_query'; -import type { GlobalTimeArgs } from '../../../common/containers/use_global_time'; -import { useHostRiskScore, HostRiskScoreQueryId } from '../../../risk_score/containers'; -export interface RiskyHostLinksProps extends Pick { - timerange: { to: string; from: string }; -} - -const QUERY_ID = HostRiskScoreQueryId.OVERVIEW_RISKY_HOSTS; - -const RiskyHostLinksComponent: React.FC = ({ - timerange, - deleteQuery, - setQuery, -}) => { - const [loading, { data, isModuleEnabled, inspect, refetch }] = useHostRiskScore({ - timerange, - }); - - useQueryInspector({ - queryId: QUERY_ID, - loading, - refetch, - setQuery, - deleteQuery, - inspect, - }); - - switch (isModuleEnabled) { - case true: - return ( - - ); - case false: - return ; - case undefined: - default: - return null; - } -}; - -export const RiskyHostLinks = React.memo(RiskyHostLinksComponent); -RiskyHostLinks.displayName = 'RiskyHostLinks'; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/navigate_to_host.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/navigate_to_host.tsx deleted file mode 100644 index afa0cfe7e9ae8c..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/navigate_to_host.tsx +++ /dev/null @@ -1,43 +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 React, { useCallback } from 'react'; -import { EuiButtonEmpty, EuiText, EuiToolTip } from '@elastic/eui'; -import { APP_UI_ID, SecurityPageName } from '../../../../common/constants'; -import { useKibana } from '../../../common/lib/kibana'; - -export const NavigateToHost: React.FC<{ name: string }> = ({ name }): JSX.Element => { - const { navigateToApp } = useKibana().services.application; - const { filterManager } = useKibana().services.data.query; - - const goToHostPage = useCallback( - (e) => { - e.preventDefault(); - filterManager.addFilters([ - { - meta: { - alias: null, - disabled: false, - negate: false, - }, - query: { match_phrase: { 'host.name': name } }, - }, - ]); - navigateToApp(APP_UI_ID, { - deepLinkId: SecurityPageName.hosts, - }); - }, - [filterManager, name, navigateToApp] - ); - return ( - - - {name} - - - ); -}; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.test.tsx deleted file mode 100644 index e8a50c83a3a273..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.test.tsx +++ /dev/null @@ -1,54 +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 React from 'react'; -import { Provider } from 'react-redux'; -import { cloneDeep } from 'lodash/fp'; -import { render, screen } from '@testing-library/react'; -import { I18nProvider } from '@kbn/i18n-react'; -import { ThemeProvider } from 'styled-components'; -import type { State } from '../../../common/store'; -import { createStore } from '../../../common/store'; -import { - createSecuritySolutionStorageMock, - kibanaObservable, - mockGlobalState, - SUB_PLUGINS_REDUCER, -} from '../../../common/mock'; -import { RiskyHostsDisabledModule } from './risky_hosts_disabled_module'; -import { mockTheme } from '../overview_cti_links/mock'; - -jest.mock('../../../common/lib/kibana'); - -describe('RiskyHostsModule', () => { - const state: State = mockGlobalState; - - const { storage } = createSecuritySolutionStorageMock(); - let store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - - beforeEach(() => { - const myState = cloneDeep(state); - store = createStore(myState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - }); - - it('renders expected children', () => { - render( - - - - - - - - ); - - expect(screen.getByTestId('risky-hosts-dashboard-links')).toBeInTheDocument(); - expect(screen.getByTestId('risky-hosts-inner-panel-danger-learn-more')).toBeInTheDocument(); - - expect(screen.getByTestId('disabled-open-in-console-button-with-tooltip')).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.tsx deleted file mode 100644 index e13089dc6404ed..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_disabled_module.tsx +++ /dev/null @@ -1,51 +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 React from 'react'; - -import * as i18n from './translations'; -import { DisabledLinkPanel } from '../link_panel/disabled_link_panel'; -import { RiskyHostsPanelView } from './risky_hosts_panel_view'; - -import { ENABLE_VIA_DEV_TOOLS } from './translations'; - -import { OpenInDevConsoleButton } from '../../../common/components/open_in_dev_console'; -import { useCheckSignalIndex } from '../../../detections/containers/detection_engine/alerts/use_check_signal_index'; -import type { LinkPanelListItem } from '../link_panel'; -import { useEnableHostRiskFromUrl } from '../../../common/hooks/use_enable_host_risk_from_url'; - -export const RISKY_HOSTS_DOC_LINK = - 'https://www.github.com/elastic/detection-rules/blob/main/docs/experimental-machine-learning/host-risk-score.md'; - -const emptyList: LinkPanelListItem[] = []; - -export const RiskyHostsDisabledModuleComponent = () => { - const loadFromUrl = useEnableHostRiskFromUrl(); - const { signalIndexExists } = useCheckSignalIndex(); - - return ( - - } - /> - ); -}; - -export const RiskyHostsDisabledModule = React.memo(RiskyHostsDisabledModuleComponent); -RiskyHostsDisabledModule.displayName = 'RiskyHostsDisabledModule'; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx deleted file mode 100644 index 46956823d19615..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.test.tsx +++ /dev/null @@ -1,82 +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 React from 'react'; -import { Provider } from 'react-redux'; -import { cloneDeep } from 'lodash/fp'; -import { render, screen } from '@testing-library/react'; -import { I18nProvider } from '@kbn/i18n-react'; -import { ThemeProvider } from 'styled-components'; -import type { State } from '../../../common/store'; -import { createStore } from '../../../common/store'; -import { - createSecuritySolutionStorageMock, - kibanaObservable, - mockGlobalState, - SUB_PLUGINS_REDUCER, -} from '../../../common/mock'; - -import { useRiskyHostsDashboardLinks } from '../../containers/overview_risky_host_links/use_risky_hosts_dashboard_links'; -import { mockTheme } from '../overview_cti_links/mock'; -import { RiskyHostsEnabledModule } from './risky_hosts_enabled_module'; -import { useDashboardButtonHref } from '../../../common/hooks/use_dashboard_button_href'; -import { RiskSeverity } from '../../../../common/search_strategy'; - -jest.mock('../../../common/lib/kibana'); - -jest.mock('../../../common/hooks/use_dashboard_button_href'); -const useRiskyHostsDashboardButtonHrefMock = useDashboardButtonHref as jest.Mock; -useRiskyHostsDashboardButtonHrefMock.mockReturnValue({ buttonHref: '/test' }); - -jest.mock('../../containers/overview_risky_host_links/use_risky_hosts_dashboard_links'); -const useRiskyHostsDashboardLinksMock = useRiskyHostsDashboardLinks as jest.Mock; -useRiskyHostsDashboardLinksMock.mockReturnValue({ - listItemsWithLinks: [{ title: 'a', count: 1, path: '/test' }], -}); - -describe('RiskyHostsEnabledModule', () => { - const state: State = mockGlobalState; - - const { storage } = createSecuritySolutionStorageMock(); - let store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - - beforeEach(() => { - const myState = cloneDeep(state); - store = createStore(myState, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - }); - - it('renders expected children', () => { - render( - - - - - - - - ); - expect(screen.getByTestId('risky-hosts-dashboard-links')).toBeInTheDocument(); - expect(screen.getByTestId('create-saved-object-success-button')).toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx deleted file mode 100644 index 49a185d6e1513d..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_enabled_module.tsx +++ /dev/null @@ -1,43 +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 React, { useMemo } from 'react'; -import { RiskyHostsPanelView } from './risky_hosts_panel_view'; -import type { LinkPanelListItem } from '../link_panel'; -import { useRiskyHostsDashboardLinks } from '../../containers/overview_risky_host_links/use_risky_hosts_dashboard_links'; -import type { HostRiskScore } from '../../../../common/search_strategy'; - -const getListItemsFromHits = (items: HostRiskScore[]): LinkPanelListItem[] => { - return items.map(({ host }) => ({ - title: host.name, - count: host.risk.calculated_score_norm, - copy: host.risk.calculated_level, - path: '', - })); -}; - -const RiskyHostsEnabledModuleComponent: React.FC<{ - from: string; - hostRiskScore?: HostRiskScore[]; - to: string; -}> = ({ hostRiskScore, to, from }) => { - const listItems = useMemo(() => getListItemsFromHits(hostRiskScore || []), [hostRiskScore]); - const { listItemsWithLinks } = useRiskyHostsDashboardLinks(to, from, listItems); - - return ( - - ); -}; - -export const RiskyHostsEnabledModule = React.memo(RiskyHostsEnabledModuleComponent); -RiskyHostsEnabledModule.displayName = 'RiskyHostsEnabledModule'; diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.test.tsx deleted file mode 100644 index 863bd4fcbd35d9..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.test.tsx +++ /dev/null @@ -1,67 +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 React from 'react'; -import { render, screen } from '@testing-library/react'; -import type { State } from '../../../common/store'; -import { createStore } from '../../../common/store'; -import { - createSecuritySolutionStorageMock, - kibanaObservable, - mockGlobalState, - SUB_PLUGINS_REDUCER, - TestProviders, -} from '../../../common/mock'; - -import { RiskyHostsPanelView } from './risky_hosts_panel_view'; -import { useDashboardButtonHref } from '../../../common/hooks/use_dashboard_button_href'; - -jest.mock('../../../common/lib/kibana'); - -jest.mock('../../../common/hooks/use_dashboard_button_href'); -const useRiskyHostsDashboardButtonHrefMock = useDashboardButtonHref as jest.Mock; -useRiskyHostsDashboardButtonHrefMock.mockReturnValue({ buttonHref: '/test' }); - -describe('RiskyHostsPanelView', () => { - const state: State = mockGlobalState; - - beforeEach(() => { - const { storage } = createSecuritySolutionStorageMock(); - const store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); - render( - - - - ); - }); - - it('renders title', () => { - expect(screen.getByTestId('header-section-title')).toHaveTextContent( - 'Current host risk scores' - ); - }); - - it('renders host number', () => { - expect(screen.getByTestId('header-panel-subtitle')).toHaveTextContent('Showing: 1 host'); - }); - - it('renders view dashboard button', () => { - expect(screen.getByTestId('create-saved-object-success-button')).toHaveAttribute( - 'href', - '/test' - ); - expect(screen.getByTestId('create-saved-object-success-button')).toHaveTextContent( - 'View dashboard' - ); - }); -}); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx deleted file mode 100644 index 7aadf6bcfa991c..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/risky_hosts_panel_view.tsx +++ /dev/null @@ -1,157 +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 React, { useCallback, useMemo, useState } from 'react'; - -import type { EuiTableFieldDataColumnType } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import type { SavedObject, SavedObjectAttributes } from '@kbn/core/types'; -import type { LinkPanelListItem } from '../link_panel'; -import { InnerLinkPanel, LinkPanel } from '../link_panel'; -import type { LinkPanelViewProps } from '../link_panel/types'; -import { Link } from '../link_panel/link'; -import * as i18n from './translations'; -import { NavigateToHost } from './navigate_to_host'; -import { HostRiskScoreQueryId } from '../../../risk_score/containers'; -import { useKibana } from '../../../common/lib/kibana'; -import { RISKY_HOSTS_DASHBOARD_TITLE } from '../../../hosts/pages/navigation/constants'; -import { useDashboardButtonHref } from '../../../common/hooks/use_dashboard_button_href'; -import { ImportSavedObjectsButton } from '../../../common/components/create_prebuilt_saved_objects/components/bulk_create_button'; -import { VIEW_DASHBOARD } from '../overview_cti_links/translations'; - -const columns: Array> = [ - { - name: 'Host Name', - field: 'title', - sortable: true, - truncateText: true, - width: '55%', - render: (name) => () as JSX.Element, - }, - { - align: 'right', - field: 'count', - name: 'Risk Score', - render: (riskScore) => - Number.isNaN(riskScore) ? riskScore : Number.parseFloat(riskScore).toFixed(2), - sortable: true, - truncateText: true, - width: '15%', - }, - { - field: 'copy', - name: 'Current Risk', - sortable: true, - truncateText: true, - width: '15%', - }, - { - field: 'path', - name: '', - render: (path: string) => () as JSX.Element, - truncateText: true, - width: '80px', - }, -]; - -const warningPanel = ( - -); - -const RiskyHostsPanelViewComponent: React.FC = ({ - isInspectEnabled, - listItems, - splitPanel, - totalCount = 0, - to, - from, -}) => { - const splitPanelElement = - typeof splitPanel === 'undefined' - ? listItems.length === 0 - ? warningPanel - : undefined - : splitPanel; - - const [dashboardUrl, setDashboardUrl] = useState(); - const { buttonHref } = useDashboardButtonHref({ - to, - from, - title: RISKY_HOSTS_DASHBOARD_TITLE, - }); - const { - services: { dashboard }, - } = useKibana(); - - const onImportDashboardSuccessCallback = useCallback( - (response: Array>) => { - const targetDashboard = response.find( - (obj) => obj.type === 'dashboard' && obj?.attributes?.title === RISKY_HOSTS_DASHBOARD_TITLE - ); - - const fetchDashboardUrl = (targetDashboardId: string | null | undefined) => { - if (to && from && targetDashboardId) { - const targetUrl = dashboard?.locator?.getRedirectUrl({ - dashboardId: targetDashboardId, - timeRange: { - to, - from, - }, - }); - - setDashboardUrl(targetUrl); - } - }; - - fetchDashboardUrl(targetDashboard?.id); - }, - [dashboard?.locator, from, to] - ); - - return ( - - ), - columns, - dataTestSubj: 'risky-hosts-dashboard-links', - defaultSortField: 'count', - defaultSortOrder: 'desc', - inspectQueryId: isInspectEnabled ? HostRiskScoreQueryId.OVERVIEW_RISKY_HOSTS : undefined, - listItems, - panelTitle: i18n.PANEL_TITLE, - splitPanel: splitPanelElement, - subtitle: useMemo( - () => ( - - ), - [totalCount] - ), - }} - /> - ); -}; - -export const RiskyHostsPanelView = React.memo(RiskyHostsPanelViewComponent); diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/translations.ts b/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/translations.ts deleted file mode 100644 index 5ba4bb2323b24b..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/components/overview_risky_host_links/translations.ts +++ /dev/null @@ -1,72 +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 { i18n } from '@kbn/i18n'; - -export const WARNING_TITLE = i18n.translate( - 'xpack.securitySolution.overview.riskyHostsDashboardWarningPanelTitle', - { - defaultMessage: 'No host risk score data available to display', - } -); - -export const WARNING_BODY = i18n.translate( - 'xpack.securitySolution.overview.riskyHostsDashboardWarningPanelBody', - { - defaultMessage: `We haven't detected any host risk score data from the hosts in your environment for the selected time range.`, - } -); - -export const DANGER_TITLE = i18n.translate( - 'xpack.securitySolution.overview.riskyHostsDashboardDangerPanelTitle', - { - defaultMessage: 'No host risk score data', - } -); - -export const DANGER_BODY = i18n.translate( - 'xpack.securitySolution.overview.riskyHostsDashboardEnableThreatIntel', - { - defaultMessage: 'You must enable the host risk module to view risky hosts.', - } -); - -export const ENABLE_VIA_DEV_TOOLS = i18n.translate( - 'xpack.securitySolution.overview.riskyHostsDashboardDangerPanelButton', - { - defaultMessage: 'Enable via Dev Tools', - } -); - -export const LEARN_MORE = i18n.translate( - 'xpack.securitySolution.overview.riskyHostsDashboardLearnMoreButton', - { - defaultMessage: 'Learn More', - } -); - -export const LINK_COPY = i18n.translate('xpack.securitySolution.overview.riskyHostsSource', { - defaultMessage: 'Source', -}); - -export const PANEL_TITLE = i18n.translate( - 'xpack.securitySolution.overview.riskyHostsDashboardTitle', - { - defaultMessage: 'Current host risk scores', - } -); - -export const IMPORT_DASHBOARD = i18n.translate('xpack.securitySolution.overview.importDasboard', { - defaultMessage: 'Import dashboard', -}); - -export const ENABLE_RISK_SCORE_POPOVER = i18n.translate( - 'xpack.securitySolution.overview.enableRiskScorePopoverTitle', - { - defaultMessage: 'Alerts need to be available before enabling module', - } -); diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_id.ts b/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_id.ts deleted file mode 100644 index 1e0758343ba474..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_id.ts +++ /dev/null @@ -1,41 +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 { useState, useEffect } from 'react'; -import type { SavedObjectAttributes } from '@kbn/securitysolution-io-ts-alerting-types'; -import { useKibana } from '../../../common/lib/kibana'; - -const DASHBOARD_REQUEST_BODY_SEARCH = '"Drilldown of Host Risk Score"'; -export const DASHBOARD_REQUEST_BODY = { - type: 'dashboard', - search: DASHBOARD_REQUEST_BODY_SEARCH, - fields: ['title'], -}; - -export const useRiskyHostsDashboardId = () => { - const savedObjectsClient = useKibana().services.savedObjects.client; - const [dashboardId, setDashboardId] = useState(); - - useEffect(() => { - if (savedObjectsClient) { - savedObjectsClient.find(DASHBOARD_REQUEST_BODY).then( - async (DashboardsSO?: { - savedObjects?: Array<{ - attributes?: SavedObjectAttributes; - id?: string; - }>; - }) => { - if (DashboardsSO?.savedObjects?.length) { - setDashboardId(DashboardsSO.savedObjects[0].id); - } - } - ); - } - }, [savedObjectsClient]); - - return dashboardId; -}; diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_links.tsx b/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_links.tsx deleted file mode 100644 index bf09bb56bb6f41..00000000000000 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_links.tsx +++ /dev/null @@ -1,73 +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 { useState, useEffect } from 'react'; -import { useKibana } from '../../../common/lib/kibana'; -import type { LinkPanelListItem } from '../../components/link_panel'; -import { useRiskyHostsDashboardId } from './use_risky_hosts_dashboard_id'; - -export const useRiskyHostsDashboardLinks = ( - to: string, - from: string, - listItems: LinkPanelListItem[] -) => { - const { dashboard } = useKibana().services; - - const dashboardId = useRiskyHostsDashboardId(); - const [listItemsWithLinks, setListItemsWithLinks] = useState([]); - - useEffect(() => { - let cancelled = false; - const createLinks = async () => { - if (dashboard?.locator && dashboardId) { - const dashboardUrls = await Promise.all( - listItems.reduce( - (acc: Array>, listItem) => - dashboard && dashboard.locator - ? [ - ...acc, - dashboard.locator.getUrl({ - dashboardId, - timeRange: { - to, - from, - }, - filters: [ - { - meta: { - alias: null, - disabled: false, - negate: false, - }, - query: { match_phrase: { 'host.name': listItem.title } }, - }, - ], - }), - ] - : acc, - [] - ) - ); - if (!cancelled && dashboardUrls.length) { - setListItemsWithLinks( - listItems.map((item, i) => ({ - ...item, - path: dashboardUrls[i], - })) - ); - } - } else { - setListItemsWithLinks(listItems); - } - }; - createLinks(); - return () => { - cancelled = true; - }; - }, [dashboard, dashboardId, from, listItems, to]); - - return { listItemsWithLinks }; -}; diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx index 2e3aa7c4d8d282..6cccf353e4b1c5 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx @@ -30,9 +30,7 @@ import { useDeepEqualSelector } from '../../common/hooks/use_selector'; import { ThreatIntelLinkPanel } from '../components/overview_cti_links'; import { useAllTiDataSources } from '../containers/overview_cti_links/use_all_ti_data_sources'; import { useUserPrivileges } from '../../common/components/user_privileges'; -import { RiskyHostLinks } from '../components/overview_risky_host_links'; import { useAlertsPrivileges } from '../../detections/containers/detection_engine/alerts/use_alerts_privileges'; -import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; import { LandingPageComponent } from '../../common/components/landing_page'; const OverviewComponent = () => { @@ -68,15 +66,6 @@ const OverviewComponent = () => { const { hasIndexRead, hasKibanaREAD } = useAlertsPrivileges(); const { tiDataSources: allTiDataSources, isInitiallyLoaded: isTiLoaded } = useAllTiDataSources(); - const riskyHostsEnabled = useIsExperimentalFeatureEnabled('riskyHostsEnabled'); - - const timerange = useMemo( - () => ({ - from, - to, - }), - [from, to] - ); return ( <> {indicesExist ? ( @@ -146,15 +135,6 @@ const OverviewComponent = () => { /> )}
- - {riskyHostsEnabled && ( - - )} -
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index baa85f6fdc93ca..7dc55e04a8e3e3 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -25517,7 +25517,6 @@ "xpack.securitySolution.overview.ctiDashboardSubtitle": "Affichage : {totalCount} {totalCount, plural, one {indicateur} other {indicateurs}}", "xpack.securitySolution.overview.overviewHost.hostsSubtitle": "Affichage de : {formattedHostEventsCount} {hostEventsCount, plural, one {événement} other {événements}}", "xpack.securitySolution.overview.overviewNetwork.networkSubtitle": "Affichage de : {formattedNetworkEventsCount} {networkEventsCount, plural, one {événement} other {événements}}", - "xpack.securitySolution.overview.riskyHostsDashboardSubtitle": "Affichage : {totalCount} {totalCount, plural, one {hôte} other {hôtes}}", "xpack.securitySolution.overview.topNLabel": "Premiers {fieldName}", "xpack.securitySolution.pages.common.updateAlertStatusFailed": "Impossible de mettre à jour { conflicts } {conflicts, plural, =1 {alerte} other {alertes}}.", "xpack.securitySolution.pages.common.updateAlertStatusFailedDetailed": "{ updated } {updated, plural, =1 {alerte a été mise à jour} other {alertes ont été mises à jour}} correctement, mais { conflicts } n'ont pas pu être mis à jour\n car { conflicts, plural, =1 {elle était} other {elles étaient}} déjà en cours de modification.", @@ -28584,7 +28583,6 @@ "xpack.securitySolution.overview.ctiDashboardOtherDatasourceTitle": "Autres", "xpack.securitySolution.overview.ctiDashboardTitle": "Threat Intelligence", "xpack.securitySolution.overview.ctiViewDasboard": "Afficher le tableau de bord", - "xpack.securitySolution.overview.enableRiskScorePopoverTitle": "Les alertes doivent être disponibles avant d'activer le module", "xpack.securitySolution.overview.endgameDnsTitle": "DNS", "xpack.securitySolution.overview.endgameFileTitle": "Fichier", "xpack.securitySolution.overview.endgameImageLoadTitle": "Chargement de la page", @@ -28610,7 +28608,6 @@ "xpack.securitySolution.overview.hostStatGroupFilebeat": "Filebeat", "xpack.securitySolution.overview.hostStatGroupWinlogbeat": "Winlogbeat", "xpack.securitySolution.overview.hostsTitle": "Événements d'hôte", - "xpack.securitySolution.overview.importDasboard": "Importer un tableau de bord", "xpack.securitySolution.overview.landingCards.box.cloudCard.desc": "Évaluez votre niveau de cloud et protégez vos charges de travail contre les attaques.", "xpack.securitySolution.overview.landingCards.box.cloudCard.title": "Protection cloud de bout en bout", "xpack.securitySolution.overview.landingCards.box.endpoint.desc": "Prévention, collecte, détection et réponse, le tout avec Elastic Agent.", @@ -28633,14 +28630,6 @@ "xpack.securitySolution.overview.packetBeatFlowTitle": "Flux", "xpack.securitySolution.overview.packetbeatTLSTitle": "TLS", "xpack.securitySolution.overview.recentTimelinesSidebarTitle": "Chronologies récentes", - "xpack.securitySolution.overview.riskyHostsDashboardDangerPanelButton": "Activer via Dev Tools", - "xpack.securitySolution.overview.riskyHostsDashboardDangerPanelTitle": "Pas de données de score de risque de l'hôte", - "xpack.securitySolution.overview.riskyHostsDashboardEnableThreatIntel": "Vous devez activer le module de risque des hôtes pour visualiser les hôtes à risque.", - "xpack.securitySolution.overview.riskyHostsDashboardLearnMoreButton": "En savoir plus", - "xpack.securitySolution.overview.riskyHostsDashboardTitle": "Scores de risque de l'hôte actuel", - "xpack.securitySolution.overview.riskyHostsDashboardWarningPanelBody": "Nous n'avons détecté aucune donnée de score de risque de l'hôte provenant des hôtes de votre environnement pour la plage temporelle sélectionnée.", - "xpack.securitySolution.overview.riskyHostsDashboardWarningPanelTitle": "Aucune donnée de score de risque de l'hôte disponible pour l'affichage", - "xpack.securitySolution.overview.riskyHostsSource": "Source", "xpack.securitySolution.overview.signalCountTitle": "Tendance des alertes", "xpack.securitySolution.overview.viewAlertsButtonLabel": "Afficher les alertes", "xpack.securitySolution.overview.viewEventsButtonLabel": "Afficher les événements", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 703ecc49772eeb..63d3a23441a0d2 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25494,7 +25494,6 @@ "xpack.securitySolution.overview.ctiDashboardSubtitle": "{totalCount} {totalCount, plural, other {個の指標}}を表示しています", "xpack.securitySolution.overview.overviewHost.hostsSubtitle": "表示中:{formattedHostEventsCount} {hostEventsCount, plural, other {イベント}}", "xpack.securitySolution.overview.overviewNetwork.networkSubtitle": "表示中:{formattedNetworkEventsCount} {networkEventsCount, plural, other {イベント}}", - "xpack.securitySolution.overview.riskyHostsDashboardSubtitle": "{totalCount} {totalCount, plural, other {個のホスト}}を表示しています", "xpack.securitySolution.overview.topNLabel": "トップ{fieldName}", "xpack.securitySolution.pages.common.updateAlertStatusFailed": "{ conflicts } {conflicts, plural, other {アラート}}を更新できませんでした。", "xpack.securitySolution.pages.common.updateAlertStatusFailedDetailed": "{ updated } {updated, plural, other {アラート}}が正常に更新されましたが、{ conflicts }は更新できませんでした。\n { conflicts, plural, other {}}すでに修正されています。", @@ -28561,7 +28560,6 @@ "xpack.securitySolution.overview.ctiDashboardOtherDatasourceTitle": "その他", "xpack.securitySolution.overview.ctiDashboardTitle": "脅威インテリジェンス", "xpack.securitySolution.overview.ctiViewDasboard": "ダッシュボードを表示", - "xpack.securitySolution.overview.enableRiskScorePopoverTitle": "モジュールを有効にする前に、アラートが使用可能でなければなりません", "xpack.securitySolution.overview.endgameDnsTitle": "DNS", "xpack.securitySolution.overview.endgameFileTitle": "ファイル", "xpack.securitySolution.overview.endgameImageLoadTitle": "画像読み込み", @@ -28587,7 +28585,6 @@ "xpack.securitySolution.overview.hostStatGroupFilebeat": "Filebeat", "xpack.securitySolution.overview.hostStatGroupWinlogbeat": "Winlogbeat", "xpack.securitySolution.overview.hostsTitle": "ホストイベント", - "xpack.securitySolution.overview.importDasboard": "ダッシュボードをインポート", "xpack.securitySolution.overview.landingCards.box.cloudCard.desc": "クラウド態勢を評価し、ワークロードを攻撃から保護します。", "xpack.securitySolution.overview.landingCards.box.cloudCard.title": "エンドツーエンドのクラウド保護", "xpack.securitySolution.overview.landingCards.box.endpoint.desc": "防御から収集、検知、対応まで実行する、Elastic Agent。", @@ -28610,14 +28607,6 @@ "xpack.securitySolution.overview.packetBeatFlowTitle": "フロー", "xpack.securitySolution.overview.packetbeatTLSTitle": "TLS", "xpack.securitySolution.overview.recentTimelinesSidebarTitle": "最近のタイムライン", - "xpack.securitySolution.overview.riskyHostsDashboardDangerPanelButton": "開発ツールで有効化", - "xpack.securitySolution.overview.riskyHostsDashboardDangerPanelTitle": "ホストリスクスコアデータがありません", - "xpack.securitySolution.overview.riskyHostsDashboardEnableThreatIntel": "リスクがあるホストを表示するには、ホストリスクモジュールを有効化する必要があります。", - "xpack.securitySolution.overview.riskyHostsDashboardLearnMoreButton": "詳細情報", - "xpack.securitySolution.overview.riskyHostsDashboardTitle": "現在のホストリスクスコア", - "xpack.securitySolution.overview.riskyHostsDashboardWarningPanelBody": "選択した期間では、ご使用の環境のホストからホストリスクスコアデータが検出されませんでした。", - "xpack.securitySolution.overview.riskyHostsDashboardWarningPanelTitle": "表示するホストリスクスコアデータがありません", - "xpack.securitySolution.overview.riskyHostsSource": "送信元", "xpack.securitySolution.overview.signalCountTitle": "アラート傾向", "xpack.securitySolution.overview.viewAlertsButtonLabel": "アラートを表示", "xpack.securitySolution.overview.viewEventsButtonLabel": "イベントを表示", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d9f2bb79ffb9ce..68ba5c3825b790 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25525,7 +25525,6 @@ "xpack.securitySolution.overview.ctiDashboardSubtitle": "正在显示:{totalCount} 个{totalCount, plural, other {指标}}", "xpack.securitySolution.overview.overviewHost.hostsSubtitle": "正在显示:{formattedHostEventsCount} 个{hostEventsCount, plural, other {事件}}", "xpack.securitySolution.overview.overviewNetwork.networkSubtitle": "正在显示:{formattedNetworkEventsCount} 个{networkEventsCount, plural, other {事件}}", - "xpack.securitySolution.overview.riskyHostsDashboardSubtitle": "正在显示:{totalCount} 台{totalCount, plural, other {主机}}", "xpack.securitySolution.overview.topNLabel": "排名靠前的{fieldName}", "xpack.securitySolution.pages.common.updateAlertStatusFailed": "无法更新{ conflicts } 个{conflicts, plural, other {告警}}。", "xpack.securitySolution.pages.common.updateAlertStatusFailedDetailed": "{ updated } 个{updated, plural, other {告警}}已成功更新,但是 { conflicts } 个无法更新,\n 因为{ conflicts, plural, other {其}}已被修改。", @@ -28592,7 +28591,6 @@ "xpack.securitySolution.overview.ctiDashboardOtherDatasourceTitle": "其他", "xpack.securitySolution.overview.ctiDashboardTitle": "威胁情报", "xpack.securitySolution.overview.ctiViewDasboard": "查看仪表板", - "xpack.securitySolution.overview.enableRiskScorePopoverTitle": "启用模块之前,告警需要处于可用状态", "xpack.securitySolution.overview.endgameDnsTitle": "DNS", "xpack.securitySolution.overview.endgameFileTitle": "文件", "xpack.securitySolution.overview.endgameImageLoadTitle": "映像加载", @@ -28618,7 +28616,6 @@ "xpack.securitySolution.overview.hostStatGroupFilebeat": "Filebeat", "xpack.securitySolution.overview.hostStatGroupWinlogbeat": "Winlogbeat", "xpack.securitySolution.overview.hostsTitle": "主机事件", - "xpack.securitySolution.overview.importDasboard": "导入仪表板", "xpack.securitySolution.overview.landingCards.box.cloudCard.desc": "评估您的云态势并防止工作负载受到攻击。", "xpack.securitySolution.overview.landingCards.box.cloudCard.title": "端到端云防护", "xpack.securitySolution.overview.landingCards.box.endpoint.desc": "防御、收集、检测和响应 — 所有这些活动均可通过 Elastic 代理来实现。", @@ -28641,14 +28638,6 @@ "xpack.securitySolution.overview.packetBeatFlowTitle": "流", "xpack.securitySolution.overview.packetbeatTLSTitle": "TLS", "xpack.securitySolution.overview.recentTimelinesSidebarTitle": "最近的时间线", - "xpack.securitySolution.overview.riskyHostsDashboardDangerPanelButton": "通过开发工具启用", - "xpack.securitySolution.overview.riskyHostsDashboardDangerPanelTitle": "无主机风险分数数据", - "xpack.securitySolution.overview.riskyHostsDashboardEnableThreatIntel": "必须启用主机风险模块才能查看有风险主机。", - "xpack.securitySolution.overview.riskyHostsDashboardLearnMoreButton": "了解详情", - "xpack.securitySolution.overview.riskyHostsDashboardTitle": "当前主机风险分数", - "xpack.securitySolution.overview.riskyHostsDashboardWarningPanelBody": "对于选定时间范围,我们尚未从您环境中的主机中检测到任何主机风险分数数据。", - "xpack.securitySolution.overview.riskyHostsDashboardWarningPanelTitle": "没有可显示的主机风险分数数据", - "xpack.securitySolution.overview.riskyHostsSource": "源", "xpack.securitySolution.overview.signalCountTitle": "告警趋势", "xpack.securitySolution.overview.viewAlertsButtonLabel": "查看告警", "xpack.securitySolution.overview.viewEventsButtonLabel": "查看事件", From 0e1bcc4427813387e66041abe5f7bf18af8f57bc Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Fri, 9 Sep 2022 17:29:07 +0200 Subject: [PATCH 020/144] [Security Solution] Skips platfom flaky tests (#140412) --- .../cypress/integration/exceptions/exceptions_flyout.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts index dfb018b4bfb5ad..20f55a4fffd4fa 100644 --- a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts @@ -303,7 +303,7 @@ describe('Exceptions flyout', () => { goToExceptionsTab(); }); - context('When updating an item with version conflict', () => { + context.skip('When updating an item with version conflict', () => { it('Displays version conflict error', () => { editException(); @@ -334,7 +334,7 @@ describe('Exceptions flyout', () => { }); }); - context('When updating an item for a list that has since been deleted', () => { + context.skip('When updating an item for a list that has since been deleted', () => { it('Displays missing exception list error', () => { editException(); From 55bd08163c5fa6358ec89b3dcee39d0468d70ad8 Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Fri, 9 Sep 2022 11:19:36 -0500 Subject: [PATCH 021/144] [Enterprise Search] pipelines component (#140419) Add a component for the search index pipelines tab with empty data panels. Updated the UI settings to reference the tab as pipelines instead of transforms as we are getting closer to settling on that name. --- .../common/ui_settings_keys.ts | 2 +- .../search_index/pipelines/pipelines.tsx | 60 +++++++++++++++++++ .../components/search_index/search_index.tsx | 19 +++--- .../enterprise_search/server/ui_settings.ts | 12 ++-- 4 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.tsx diff --git a/x-pack/plugins/enterprise_search/common/ui_settings_keys.ts b/x-pack/plugins/enterprise_search/common/ui_settings_keys.ts index bccb83e63e01bc..1007c3f4421af4 100644 --- a/x-pack/plugins/enterprise_search/common/ui_settings_keys.ts +++ b/x-pack/plugins/enterprise_search/common/ui_settings_keys.ts @@ -6,4 +6,4 @@ */ export const enterpriseSearchFeatureId = 'enterpriseSearch'; -export const enableIndexTransformsTab = 'enterpriseSearch:enableIndexTransformsTab'; +export const enableIndexPipelinesTab = 'enterpriseSearch:enableIndexTransformsTab'; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.tsx new file mode 100644 index 00000000000000..c80f4cd669273f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines.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 { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { DataPanel } from '../../../../shared/data_panel/data_panel'; + +export const SearchIndexPipelines: React.FC = () => { + return ( + <> + + + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.ingestionPipeline.title', + { + defaultMessage: 'Ingest Pipelines', + } + )} + + } + iconType="logstashInput" + > +
+ + + + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.mlInferencePipelines.title', + { + defaultMessage: 'ML Inference pipelines', + } + )} + + } + iconType="compute" + > +
+ + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx index a376b4dd5bd48b..b998fa5d10db2a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx @@ -17,7 +17,7 @@ import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { Status } from '../../../../../common/types/api'; -import { enableIndexTransformsTab } from '../../../../../common/ui_settings_keys'; +import { enableIndexPipelinesTab } from '../../../../../common/ui_settings_keys'; import { generateEncodedPath } from '../../../shared/encode_path_params'; import { KibanaLogic } from '../../../shared/kibana'; import { FetchIndexApiLogic } from '../../api/index/fetch_index_api_logic'; @@ -38,16 +38,17 @@ import { SearchIndexDocuments } from './documents'; import { SearchIndexIndexMappings } from './index_mappings'; import { IndexNameLogic } from './index_name_logic'; import { SearchIndexOverview } from './overview'; +import { SearchIndexPipelines } from './pipelines/pipelines'; export enum SearchIndexTabId { // all indices OVERVIEW = 'overview', DOCUMENTS = 'documents', INDEX_MAPPINGS = 'index_mappings', + PIPELINES = 'pipelines', // connector indices CONFIGURATION = 'configuration', SCHEDULING = 'scheduling', - TRANSFORMS = 'transforms', // crawler indices DOMAIN_MANAGEMENT = 'domain_management', } @@ -64,7 +65,7 @@ export const SearchIndex: React.FC = () => { const { indexName } = useValues(IndexNameLogic); - const transformsEnabled = uiSettings?.get(enableIndexTransformsTab) ?? false; + const pipelinesEnabled = uiSettings?.get(enableIndexPipelinesTab) ?? false; const ALL_INDICES_TABS: EuiTabbedContentTab[] = [ { @@ -124,12 +125,12 @@ export const SearchIndex: React.FC = () => { }, ]; - const TRANSFORMS_TAB: EuiTabbedContentTab[] = [ + const PIPELINES_TAB: EuiTabbedContentTab[] = [ { - content:
, - id: SearchIndexTabId.TRANSFORMS, - name: i18n.translate('xpack.enterpriseSearch.content.searchIndex.transformsTabLabel', { - defaultMessage: 'Transforms', + content: , + id: SearchIndexTabId.PIPELINES, + name: i18n.translate('xpack.enterpriseSearch.content.searchIndex.pipelinesTabLabel', { + defaultMessage: 'Pipelines', }), }, ]; @@ -138,7 +139,7 @@ export const SearchIndex: React.FC = () => { ...ALL_INDICES_TABS, ...(isConnectorIndex(indexData) ? CONNECTOR_TABS : []), ...(isCrawlerIndex(indexData) ? CRAWLER_TABS : []), - ...(transformsEnabled && isConnectorIndex(indexData) ? TRANSFORMS_TAB : []), + ...(pipelinesEnabled ? PIPELINES_TAB : []), ]; const selectedTab = tabs.find((tab) => tab.id === tabId); diff --git a/x-pack/plugins/enterprise_search/server/ui_settings.ts b/x-pack/plugins/enterprise_search/server/ui_settings.ts index 15241cc5fe890c..0497aa54d2eecd 100644 --- a/x-pack/plugins/enterprise_search/server/ui_settings.ts +++ b/x-pack/plugins/enterprise_search/server/ui_settings.ts @@ -9,19 +9,19 @@ import { schema } from '@kbn/config-schema'; import { UiSettingsParams } from '@kbn/core/types'; import { i18n } from '@kbn/i18n'; -import { enterpriseSearchFeatureId, enableIndexTransformsTab } from '../common/ui_settings_keys'; +import { enterpriseSearchFeatureId, enableIndexPipelinesTab } from '../common/ui_settings_keys'; /** * uiSettings definitions for Enterprise Search */ export const uiSettings: Record> = { - [enableIndexTransformsTab]: { + [enableIndexPipelinesTab]: { category: [enterpriseSearchFeatureId], - description: i18n.translate('xpack.enterpriseSearch.uiSettings.indexTransforms.description', { - defaultMessage: 'Enable the new index transforms tab in Enterprise Search.', + description: i18n.translate('xpack.enterpriseSearch.uiSettings.indexPipelines.description', { + defaultMessage: 'Enable the new index pipelines tab in Enterprise Search.', }), - name: i18n.translate('xpack.enterpriseSearch.uiSettings.indexTransforms.name', { - defaultMessage: 'Enable index transforms', + name: i18n.translate('xpack.enterpriseSearch.uiSettings.indexPipelines.name', { + defaultMessage: 'Enable index pipelines', }), requiresPageReload: false, schema: schema.boolean(), From fa85014ffcd61a17de12d802037044346d584049 Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Fri, 9 Sep 2022 12:22:06 -0400 Subject: [PATCH 022/144] [Security Solution][Endpoint] Changed test generator data loader so that endpoints have same version as Kibana (#140232) * Created `HostMetadataInterface` which is not set to Immutable, + add `type` to `agent` object * Changed `randomVersion()` to generate a combination of 7x and 8x version numbers * new standalone Endpoint metadata generator * Change `EndpointDocGenerator` to use `EndpointMetadataGenerator` internally * Change data indexer script to allow EndpointDocGenerator class to be passed in * Change Endpoint loading script (resolver_generator_script) so that Endpoints are created at same version as Kibana Co-authored-by: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../data_generators/base_data_generator.ts | 4 +- .../endpoint_metadata_generator.ts | 149 ++++++++++++++ .../common/endpoint/generate_data.test.ts | 2 +- .../common/endpoint/generate_data.ts | 182 ++++-------------- .../common/endpoint/index_data.ts | 6 +- .../common/endpoint/types/index.ts | 11 +- .../endpoint_hosts/store/middleware.test.ts | 18 +- .../isometric_taxi_layout.test.ts.snap | 72 +++---- .../scripts/endpoint/common/stack_services.ts | 22 +++ .../endpoint/resolver_generator_script.ts | 42 +++- .../apps/endpoint/endpoint_list.ts | 58 +++--- 11 files changed, 326 insertions(+), 240 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts index 8c917b4ef6898f..868129f3a67374 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts @@ -167,7 +167,9 @@ export class BaseDataGenerator { } protected randomVersion(): string { - return [7, ...this.randomNGenerator(20, 2)].map((x) => x.toString()).join('.'); + // the `major` is sometimes (30%) 7 and most of the time (70%) 8 + const major = this.randomBoolean(0.4) ? 7 : 8; + return [major, ...this.randomNGenerator(20, 2)].map((x) => x.toString()).join('.'); } protected randomChoice(choices: T[] | readonly T[]): T { diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts new file mode 100644 index 00000000000000..67ff2d3605093b --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts @@ -0,0 +1,149 @@ +/* + * 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 type { DeepPartial } from 'utility-types'; +import { merge } from 'lodash'; +import { gte } from 'semver'; +import { BaseDataGenerator } from './base_data_generator'; +import type { HostMetadataInterface, OSFields } from '../types'; +import { EndpointStatus, HostPolicyResponseActionStatus } from '../types'; + +/** + * Metadata generator for docs that are sent by the Endpoint running on hosts + */ +export class EndpointMetadataGenerator extends BaseDataGenerator { + /** Generate an Endpoint host metadata document */ + generate(overrides: DeepPartial = {}): HostMetadataInterface { + const ts = overrides['@timestamp'] ?? new Date().getTime(); + const hostName = this.randomHostname(); + const agentVersion = overrides?.agent?.version ?? this.randomVersion(); + const agentId = this.seededUUIDv4(); + const isIsolated = this.randomBoolean(0.3); + const capabilities = ['isolation']; + + // v8.4 introduced additional endpoint capabilities + if (gte(agentVersion, '8.4.0')) { + capabilities.push('kill_process', 'suspend_process', 'running_processes'); + } + + const hostMetadataDoc: HostMetadataInterface = { + '@timestamp': ts, + event: { + created: ts, + id: this.seededUUIDv4(), + kind: 'metric', + category: ['host'], + type: ['info'], + module: 'endpoint', + action: 'endpoint_metadata', + dataset: 'endpoint.metadata', + }, + data_stream: { + type: 'metrics', + dataset: 'endpoint.metadata', + namespace: 'default', + }, + agent: { + version: agentVersion, + id: agentId, + type: 'endpoint', + }, + elastic: { + agent: { + id: agentId, + }, + }, + host: { + id: this.seededUUIDv4(), + hostname: hostName, + name: hostName, + architecture: this.randomString(10), + ip: this.randomArray(3, () => this.randomIP()), + mac: this.randomArray(3, () => this.randomMac()), + os: this.randomOsFields(), + }, + Endpoint: { + status: EndpointStatus.enrolled, + policy: { + applied: { + name: 'With Eventing', + id: 'C2A9093E-E289-4C0A-AA44-8C32A414FA7A', + status: HostPolicyResponseActionStatus.success, + endpoint_policy_version: 3, + version: 5, + }, + }, + configuration: { + isolation: isIsolated, + }, + state: { + isolation: isIsolated, + }, + capabilities, + }, + }; + + return merge(hostMetadataDoc, overrides); + } + + protected randomOsFields(): OSFields { + return this.randomChoice([ + { + name: 'Windows', + full: 'Windows 10', + version: '10.0', + platform: 'Windows', + family: 'windows', + Ext: { + variant: 'Windows Pro', + }, + }, + { + name: 'Windows', + full: 'Windows Server 2016', + version: '10.0', + platform: 'Windows', + family: 'windows', + Ext: { + variant: 'Windows Server', + }, + }, + { + name: 'Windows', + full: 'Windows Server 2012', + version: '6.2', + platform: 'Windows', + family: 'windows', + Ext: { + variant: 'Windows Server', + }, + }, + { + name: 'Windows', + full: 'Windows Server 2012R2', + version: '6.3', + platform: 'Windows', + family: 'windows', + Ext: { + variant: 'Windows Server Release 2', + }, + }, + { + Ext: { + variant: 'Debian', + }, + kernel: '4.19.0-21-cloud-amd64 #1 SMP Debian 4.19.249-2 (2022-06-30)', + name: 'Linux', + family: 'debian', + type: 'linux', + version: '10.12', + platform: 'debian', + full: 'Debian 10.12', + }, + ]); + } +} diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts index 1586e47aa1f4c9..a005004a906820 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.test.ts @@ -504,7 +504,7 @@ describe('data generator', () => { events[previousProcessEventIndex].process?.parent?.entity_id ); expect(events[events.length - 1].event?.kind).toEqual('alert'); - expect(events[events.length - 1].event?.category).toEqual('malware'); + expect(events[events.length - 1].event?.category).toEqual('behavior'); }); }); diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index c9b554fc89031d..59808b1df430c1 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -14,17 +14,17 @@ import type { KibanaAssetReference, } from '@kbn/fleet-plugin/common'; import { agentPolicyStatuses } from '@kbn/fleet-plugin/common'; +import { EndpointMetadataGenerator } from './data_generators/endpoint_metadata_generator'; import type { AlertEvent, DataStream, - Host, HostMetadata, + HostMetadataInterface, HostPolicyResponse, - OSFields, PolicyData, SafeEndpointEvent, } from './types'; -import { EndpointStatus, HostPolicyResponseActionStatus } from './types'; +import { HostPolicyResponseActionStatus } from './types'; import { policyFactory } from './models/policy_config'; import { ancestryArray, @@ -49,55 +49,6 @@ export type Event = AlertEvent | SafeEndpointEvent; */ export const ANCESTRY_LIMIT: number = 2; -const Windows: OSFields[] = [ - { - name: 'Windows', - full: 'Windows 10', - version: '10.0', - platform: 'Windows', - family: 'windows', - Ext: { - variant: 'Windows Pro', - }, - }, - { - name: 'Windows', - full: 'Windows Server 2016', - version: '10.0', - platform: 'Windows', - family: 'windows', - Ext: { - variant: 'Windows Server', - }, - }, - { - name: 'Windows', - full: 'Windows Server 2012', - version: '6.2', - platform: 'Windows', - family: 'windows', - Ext: { - variant: 'Windows Server', - }, - }, - { - name: 'Windows', - full: 'Windows Server 2012R2', - version: '6.3', - platform: 'Windows', - family: 'windows', - Ext: { - variant: 'Windows Server Release 2', - }, - }, -]; - -const Linux: OSFields[] = []; - -const Mac: OSFields[] = []; - -const OS: OSFields[] = [...Windows, ...Mac, ...Linux]; - const POLICY_RESPONSE_STATUSES: HostPolicyResponseActionStatus[] = [ HostPolicyResponseActionStatus.success, HostPolicyResponseActionStatus.failure, @@ -105,13 +56,7 @@ const POLICY_RESPONSE_STATUSES: HostPolicyResponseActionStatus[] = [ HostPolicyResponseActionStatus.unsupported, ]; -const APPLIED_POLICIES: Array<{ - name: string; - id: string; - status: HostPolicyResponseActionStatus; - endpoint_policy_version: number; - version: number; -}> = [ +const APPLIED_POLICIES: Array = [ { name: 'Default', id: '00000000-0000-0000-0000-000000000000', @@ -231,38 +176,7 @@ const OTHER_EVENT_CATEGORIES: Record< }, }; -interface HostInfo { - elastic: { - agent: { - id: string; - }; - }; - agent: { - version: string; - id: string; - type: string; - }; - host: Host; - Endpoint: { - status: EndpointStatus; - policy: { - applied: { - id: string; - status: HostPolicyResponseActionStatus; - name: string; - endpoint_policy_version: number; - version: number; - }; - }; - configuration?: { - isolation: boolean; - }; - state?: { - isolation: boolean; - }; - capabilities?: string[]; - }; -} +type CommonHostInfo = Pick; interface NodeState { event: Event; @@ -403,17 +317,32 @@ const alertsDefaultDataStream = { namespace: 'default', }; +/** + * Generator to create various ElasticSearch documents that are normally streamed by the Endpoint. + * + * NOTE: this generator currently reuses certain data (ex. `this.commonInfo`) across several + * documents, thus use caution if manipulating/mutating value in the generated data + * (ex. in tests). Individual standalone generators exist, whose generated data does not + * contain shared data structures. + */ export class EndpointDocGenerator extends BaseDataGenerator { - commonInfo: HostInfo; + commonInfo: CommonHostInfo; sequence: number = 0; + private readonly metadataGenerator: EndpointMetadataGenerator; + /** * The EndpointDocGenerator parameters * * @param seed either a string to seed the random number generator or a random number generator function + * @param MetadataGenerator */ - constructor(seed: string | seedrandom.prng = Math.random().toString()) { + constructor( + seed: string | seedrandom.prng = Math.random().toString(), + MetadataGenerator: typeof EndpointMetadataGenerator = EndpointMetadataGenerator + ) { super(seed); + this.metadataGenerator = new MetadataGenerator(seed); this.commonInfo = this.createHostData(); } @@ -456,47 +385,12 @@ export class EndpointDocGenerator extends BaseDataGenerator { }; } - private createHostData(): HostInfo { - const hostName = this.randomHostname(); - const isIsolated = this.randomBoolean(0.3); - const agentVersion = this.randomVersion(); - const capabilities = ['isolation', 'kill_process', 'suspend_process', 'running_processes']; - const agentId = this.seededUUIDv4(); + private createHostData(): CommonHostInfo { + const { agent, elastic, host, Endpoint } = this.metadataGenerator.generate({ + Endpoint: { policy: { applied: this.randomChoice(APPLIED_POLICIES) } }, + }); - return { - agent: { - version: agentVersion, - id: agentId, - type: 'endpoint', - }, - elastic: { - agent: { - id: agentId, - }, - }, - host: { - id: this.seededUUIDv4(), - hostname: hostName, - name: hostName, - architecture: this.randomString(10), - ip: this.randomArray(3, () => this.randomIP()), - mac: this.randomArray(3, () => this.randomMac()), - os: this.randomChoice(OS), - }, - Endpoint: { - status: EndpointStatus.enrolled, - policy: { - applied: this.randomChoice(APPLIED_POLICIES), - }, - configuration: { - isolation: isIsolated, - }, - state: { - isolation: isIsolated, - }, - capabilities, - }, - }; + return { agent, elastic, host, Endpoint }; } /** @@ -508,21 +402,11 @@ export class EndpointDocGenerator extends BaseDataGenerator { ts = new Date().getTime(), metadataDataStream = metadataDefaultDataStream ): HostMetadata { - return { + return this.metadataGenerator.generate({ '@timestamp': ts, - event: { - created: ts, - id: this.seededUUIDv4(), - kind: 'metric', - category: ['host'], - type: ['info'], - module: 'endpoint', - action: 'endpoint_metadata', - dataset: 'endpoint.metadata', - }, - ...this.commonInfo, data_stream: metadataDataStream, - }; + ...this.commonInfo, + }); } /** @@ -1628,7 +1512,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { } /** - * Generates an Ingest `package policy` that includes the Endpoint Policy data + * Generates a Fleet `package policy` that includes the Endpoint Policy data */ public generatePolicyPackagePolicy(): PolicyData { const created = new Date(Date.now() - 8.64e7).toISOString(); // 24h ago @@ -1673,7 +1557,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { } /** - * Generate an Agent Policy (ingest) + * Generate an Agent Policy (Fleet) */ public generateAgentPolicy(): GetAgentPoliciesResponseItem { // FIXME: remove and use new FleetPackagePolicyGenerator (#2262) @@ -1693,7 +1577,7 @@ export class EndpointDocGenerator extends BaseDataGenerator { } /** - * Generate an EPM Package for Endpoint + * Generate a Fleet EPM Package for Endpoint */ public generateEpmPackage(): GetPackagesResponse['items'][0] { return { diff --git a/x-pack/plugins/security_solution/common/endpoint/index_data.ts b/x-pack/plugins/security_solution/common/endpoint/index_data.ts index ea01e62fbc8077..4971dc83c29aa1 100644 --- a/x-pack/plugins/security_solution/common/endpoint/index_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/index_data.ts @@ -43,6 +43,7 @@ export type IndexedHostsAndAlertsResponse = IndexedHostsResponse; * @param alertsPerHost * @param fleet * @param options + * @param DocGenerator */ export async function indexHostsAndAlerts( client: Client, @@ -56,7 +57,8 @@ export async function indexHostsAndAlerts( alertIndex: string, alertsPerHost: number, fleet: boolean, - options: TreeOptions = {} + options: TreeOptions = {}, + DocGenerator: typeof EndpointDocGenerator = EndpointDocGenerator ): Promise { const random = seedrandom(seed); const epmEndpointPackage = await getEndpointPackageInfo(kbnClient); @@ -91,7 +93,7 @@ export async function indexHostsAndAlerts( const realPolicies: Record = {}; for (let i = 0; i < numHosts; i++) { - const generator = new EndpointDocGenerator(random); + const generator = new DocGenerator(random); const indexedHosts = await indexEndpointHostDocs({ numDocs, client, diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 0f791a1f409d1f..cdadf9619f0087 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -492,9 +492,11 @@ export type HostInfo = Immutable<{ }; }>; -// HostMetadataDetails is now just HostMetadata -// HostDetails is also just HostMetadata -export type HostMetadata = Immutable<{ +// Host metadata document streamed up to ES by the Endpoint running on host machines. +// NOTE: `HostMetadata` type is the original and defined as Immutable. If needing to +// work with metadata that is not mutable, use `HostMetadataInterface` +export type HostMetadata = Immutable; +export interface HostMetadataInterface { '@timestamp': number; event: { created: number; @@ -542,10 +544,11 @@ export type HostMetadata = Immutable<{ agent: { id: string; version: string; + type: string; }; host: Host; data_stream: DataStream; -}>; +} export type UnitedAgentMetadata = Immutable<{ agent: { diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts index 7d1fd0a3d77fee..c2cecdba29b3d3 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts @@ -255,15 +255,15 @@ describe('endpoint list middleware', () => { query: { agent_ids: [ '0dc3661d-6e67-46b0-af39-6f12b025fcb0', - 'a8e32a61-2685-47f0-83eb-edf157b8e616', - '37e219a8-fe16-4da9-bf34-634c5824b484', - '2484eb13-967e-4491-bf83-dffefdfe607c', - '0bc08ef6-6d6a-4113-92f2-b97811187c63', - 'f4127d87-b567-4a6e-afa6-9a1c7dc95f01', - 'f9ab5b8c-a43e-4e80-99d6-11570845a697', - '406c4b6a-ca57-4bd1-bc66-d9d999df3e70', - '2da1dd51-f7af-4f0e-b64c-e7751c74b0e7', - '89a94ea4-073c-4cb6-90a2-500805837027', + '34634c58-24b4-4448-80f4-107fb9918494', + '5a1298e3-e607-4bc0-8ef6-6d6a811312f2', + '78c54b13-596d-4891-95f4-80092d04454b', + '445f1fd2-5f81-4ddd-bdb6-f0d1bf2efe90', + 'd77a3fc6-3096-4852-a6ee-f6b09278fbc6', + '892fcccf-1bd8-45a2-a9cc-9a7860a3cb81', + '693a3110-5ba0-4284-a264-5d78301db08c', + '554db084-64fa-4e4a-ba47-2ba713f9932b', + 'c217deb6-674d-4f97-bb1d-a3a04238e6d7', ], }, }); diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap index b033febcd1ac8f..f6afb2bbe033ca 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/__snapshots__/isometric_taxi_layout.test.ts.snap @@ -15,11 +15,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "A", - "process.name": "lsass.exe", + "process.name": "mimikatz.exe", "process.parent.entity_id": "", }, "id": "A", - "name": "lsass.exe", + "name": "mimikatz.exe", "parent": undefined, "stats": Object { "byCategory": Object {}, @@ -33,11 +33,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "A", - "process.name": "lsass.exe", + "process.name": "mimikatz.exe", "process.parent.entity_id": "", }, "id": "A", - "name": "lsass.exe", + "name": "mimikatz.exe", "parent": undefined, "stats": Object { "byCategory": Object {}, @@ -58,11 +58,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "A", - "process.name": "mimikatz.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "", }, "id": "A", - "name": "mimikatz.exe", + "name": "explorer.exe", "parent": undefined, "stats": Object { "byCategory": Object {}, @@ -88,11 +88,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "C", - "process.name": "lsass.exe", + "process.name": "iexlorer.exe", "process.parent.entity_id": "A", }, "id": "C", - "name": "lsass.exe", + "name": "iexlorer.exe", "parent": "A", "stats": Object { "byCategory": Object {}, @@ -103,11 +103,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "I", - "process.name": "notepad.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "A", }, "id": "I", - "name": "notepad.exe", + "name": "explorer.exe", "parent": "A", "stats": Object { "byCategory": Object {}, @@ -118,11 +118,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "D", - "process.name": "lsass.exe", + "process.name": "powershell.exe", "process.parent.entity_id": "B", }, "id": "D", - "name": "lsass.exe", + "name": "powershell.exe", "parent": "B", "stats": Object { "byCategory": Object {}, @@ -148,11 +148,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "F", - "process.name": "powershell.exe", + "process.name": "notepad.exe", "process.parent.entity_id": "C", }, "id": "F", - "name": "powershell.exe", + "name": "notepad.exe", "parent": "C", "stats": Object { "byCategory": Object {}, @@ -178,11 +178,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "H", - "process.name": "notepad.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "G", }, "id": "H", - "name": "notepad.exe", + "name": "explorer.exe", "parent": "G", "stats": Object { "byCategory": Object {}, @@ -439,11 +439,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "A", - "process.name": "mimikatz.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "", }, "id": "A", - "name": "mimikatz.exe", + "name": "explorer.exe", "parent": undefined, "stats": Object { "byCategory": Object {}, @@ -475,11 +475,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "C", - "process.name": "lsass.exe", + "process.name": "iexlorer.exe", "process.parent.entity_id": "A", }, "id": "C", - "name": "lsass.exe", + "name": "iexlorer.exe", "parent": "A", "stats": Object { "byCategory": Object {}, @@ -493,11 +493,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "I", - "process.name": "notepad.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "A", }, "id": "I", - "name": "notepad.exe", + "name": "explorer.exe", "parent": "A", "stats": Object { "byCategory": Object {}, @@ -511,11 +511,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "D", - "process.name": "lsass.exe", + "process.name": "powershell.exe", "process.parent.entity_id": "B", }, "id": "D", - "name": "lsass.exe", + "name": "powershell.exe", "parent": "B", "stats": Object { "byCategory": Object {}, @@ -547,11 +547,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "F", - "process.name": "powershell.exe", + "process.name": "notepad.exe", "process.parent.entity_id": "C", }, "id": "F", - "name": "powershell.exe", + "name": "notepad.exe", "parent": "C", "stats": Object { "byCategory": Object {}, @@ -583,11 +583,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "H", - "process.name": "notepad.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "G", }, "id": "H", - "name": "notepad.exe", + "name": "explorer.exe", "parent": "G", "stats": Object { "byCategory": Object {}, @@ -608,11 +608,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "A", - "process.name": "mimikatz.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "", }, "id": "A", - "name": "mimikatz.exe", + "name": "explorer.exe", "parent": undefined, "stats": Object { "byCategory": Object {}, @@ -623,11 +623,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "B", - "process.name": "mimikatz.exe", + "process.name": "notepad.exe", "process.parent.entity_id": "A", }, "id": "B", - "name": "mimikatz.exe", + "name": "notepad.exe", "parent": "A", "stats": Object { "byCategory": Object {}, @@ -661,11 +661,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "A", - "process.name": "mimikatz.exe", + "process.name": "explorer.exe", "process.parent.entity_id": "", }, "id": "A", - "name": "mimikatz.exe", + "name": "explorer.exe", "parent": undefined, "stats": Object { "byCategory": Object {}, @@ -679,11 +679,11 @@ Object { "data": Object { "@timestamp": 1606234833273, "process.entity_id": "B", - "process.name": "mimikatz.exe", + "process.name": "notepad.exe", "process.parent.entity_id": "A", }, "id": "B", - "name": "mimikatz.exe", + "name": "notepad.exe", "parent": "A", "stats": Object { "byCategory": Object {}, diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts index 72dbf3ade5e4a2..213f839421a71f 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts @@ -8,6 +8,7 @@ import { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/tooling-log'; import { KbnClient } from '@kbn/test'; +import type { StatusResponse } from '@kbn/core-status-common-internal'; import { createSecuritySuperuser } from './security_user_services'; export interface RuntimeServices { @@ -116,3 +117,24 @@ export const createKbnClient = ({ return new KbnClient({ log, url: kbnUrl }); }; + +/** + * Retrieves the Stack (kibana/ES) version from the `/api/status` kibana api + * @param kbnClient + */ +export const fetchStackVersion = async (kbnClient: KbnClient): Promise => { + const status = ( + await kbnClient.request({ + method: 'GET', + path: '/api/status', + }) + ).data; + + if (!status?.version?.number) { + throw new Error( + `unable to get stack version from '/api/status' \n${JSON.stringify(status, null, 2)}` + ); + } + + return status.version.number; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts index 9eb03dd80e3269..a871151ed0b0d3 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts @@ -5,7 +5,7 @@ * 2.0. */ -/* eslint-disable no-console */ +/* eslint-disable no-console,max-classes-per-file */ import yargs from 'yargs'; import fs from 'fs'; import { Client, errors } from '@elastic/elasticsearch'; @@ -14,8 +14,10 @@ import { CA_CERT_PATH } from '@kbn/dev-utils'; import { ToolingLog } from '@kbn/tooling-log'; import type { KbnClientOptions } from '@kbn/test'; import { KbnClient } from '@kbn/test'; +import { EndpointMetadataGenerator } from '../../common/endpoint/data_generators/endpoint_metadata_generator'; import { indexHostsAndAlerts } from '../../common/endpoint/index_data'; import { ANCESTRY_LIMIT, EndpointDocGenerator } from '../../common/endpoint/generate_data'; +import { fetchStackVersion } from './common/stack_services'; main(); @@ -249,6 +251,13 @@ async function main() { type: 'string', default: '', }, + randomVersions: { + describe: + 'By default, the data generated (that contains a stack version - ex: `agent.version`) will have a ' + + 'version number set to be the same as the version of the running stack. Using this flag (`--randomVersions=true`) ' + + 'will result in random version being generated', + default: false, + }, }).argv; let ca: Buffer; @@ -323,11 +332,14 @@ async function main() { } let seed = argv.seed; + if (!seed) { seed = Math.random().toString(); console.log(`No seed supplied, using random seed: ${seed}`); } + const startTime = new Date().getTime(); + if (argv.fleet && !argv.withNewUser) { // warn and exit when using fleet flag console.log( @@ -336,6 +348,29 @@ async function main() { // eslint-disable-next-line no-process-exit process.exit(0); } + + let DocGenerator: typeof EndpointDocGenerator = EndpointDocGenerator; + + // If `--randomVersions` is NOT set, then use custom generator that ensures all data generated + // has a stack version number that matches that of the running stack + if (!argv.randomVersions) { + const stackVersion = await fetchStackVersion(kbnClient); + + // Document Generator override that uses a custom Endpoint Metadata generator and sets the + // `agent.version` to the current version + DocGenerator = class extends EndpointDocGenerator { + constructor(...args: ConstructorParameters) { + const MetadataGenerator = class extends EndpointMetadataGenerator { + protected randomVersion(): string { + return stackVersion; + } + }; + + super(args[0], MetadataGenerator); + } + }; + } + await indexHostsAndAlerts( client, kbnClient, @@ -360,10 +395,11 @@ async function main() { ancestryArraySize: argv.ancestryArraySize, eventsDataStream: EndpointDocGenerator.createDataStreamFromIndex(argv.eventIndex), alertsDataStream: EndpointDocGenerator.createDataStreamFromIndex(argv.alertIndex), - } + }, + DocGenerator ); - // delete endpoint_user after + // delete endpoint_user after if (user) { const deleted = await deleteUser(client, user.username); if (deleted.found) { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index 81a1dc109b562d..8c8629002c93f2 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -34,28 +34,38 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'Actions', ], [ - 'Host-ku5jy6j0pw', + 'Host-nyierkw2gu', 'x', 'x', - 'Unsupported', + 'Failure', 'Windows', - '10.12.215.130, 10.130.188.228,10.19.102.141', - '7.0.13', + '10.180.151.227, 10.44.18.210', + '7.1.9', 'x', '', ], [ - 'Host-ntr4rkj24m', + 'Host-rs9wp4o6l9', 'x', 'x', - 'Success', + 'Warning', 'Windows', - '10.36.46.252, 10.222.152.110', - '7.4.13', + '10.218.38.118, 10.80.35.162', + '8.0.8', + 'x', + '', + ], + [ + 'Host-u5jy6j0pwb', + 'x', + 'x', + 'Warning', + 'Linux', + '10.87.11.145, 10.117.106.109,10.242.136.97', + '7.13.1', 'x', '', ], - ['Host-q9qenwrl9k', 'x', 'x', 'Warning', 'Windows', '10.206.226.90', '7.11.10', 'x', ''], ]; const formattedTableData = async () => { @@ -183,38 +193,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(tableData).to.eql(expectedDataFromQuery); }); - it('for the kql filtering for united.endpoint.host.hostname : "Host-ku5jy6j0pw", table shows 1 item', async () => { + it('for the kql filtering for united.endpoint.host.hostname, table shows 1 item', async () => { + const expectedDataFromQuery = [...expectedData.slice(0, 2).map((row) => [...row])]; + const hostName = expectedDataFromQuery[1][0]; const adminSearchBar = await testSubjects.find('adminSearchBar'); await adminSearchBar.clearValueWithKeyboard(); await adminSearchBar.type( - 'united.endpoint.host.hostname : "Host-ku5jy6j0pw" or host.hostname : "Host-ku5jy6j0pw" ' + `united.endpoint.host.hostname : "${hostName}" or host.hostname : "${hostName}" ` ); const querySubmitButton = await testSubjects.find('querySubmitButton'); await querySubmitButton.click(); - const expectedDataFromQuery = [ - [ - 'Endpoint', - 'Agent status', - 'Policy', - 'Policy status', - 'OS', - 'IP address', - 'Version', - 'Last active', - 'Actions', - ], - [ - 'Host-ku5jy6j0pw', - 'x', - 'x', - 'Unsupported', - 'Windows', - '10.12.215.130, 10.130.188.228,10.19.102.141', - '7.0.13', - 'x', - '', - ], - ]; await pageObjects.endpoint.waitForTableToHaveNumberOfEntries( 'endpointListTable', 1, From b0b9b585fb1aa42a3078e67e6e8d1a3d3b68ae02 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 9 Sep 2022 10:27:50 -0600 Subject: [PATCH 023/144] skip failing test suite (#140248) --- .../apps/observability/pages/alerts/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts index cdb0ea37a6417c..f2a59d6b22b2e7 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts @@ -20,7 +20,8 @@ export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const find = getService('find'); - describe('Observability alerts', function () { + // Failing: See https://github.com/elastic/kibana/issues/140248 + describe.skip('Observability alerts', function () { this.tags('includeFirefox'); const testSubjects = getService('testSubjects'); From bc40e3c39f3a0f6c92f39dc2afacd9b15c285f2e Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Fri, 9 Sep 2022 13:13:11 -0400 Subject: [PATCH 024/144] feat(slo): introduce SLO transform installer (#140224) --- .../observability/server/assets/constants.ts | 5 +- .../slo_transform_template.ts | 42 ++++ x-pack/plugins/observability/server/plugin.ts | 1 - .../observability/server/routes/slo/route.ts | 43 +++- .../server/services/slo/fixtures/slo.ts | 51 +++++ .../server/services/slo/index.ts | 1 + .../server/services/slo/resource_installer.ts | 4 +- .../services/slo/slo_repository.test.ts | 36 +--- .../apm_transaction_duration.test.ts.snap | 139 +++++++++++++ .../apm_transaction_error_rate.test.ts.snap | 177 +++++++++++++++++ .../apm_transaction_duration.test.ts | 41 ++++ .../apm_transaction_duration.ts | 179 +++++++++++++++++ .../apm_transaction_error_rate.test.ts | 48 +++++ .../apm_transaction_error_rate.ts | 185 ++++++++++++++++++ .../slo/transform_generators/index.ts | 10 + .../transform_generator.ts | 13 ++ .../services/slo/transform_installer.test.ts | 102 ++++++++++ .../services/slo/transform_installer.ts | 52 +++++ .../observability/server/types/models/slo.ts | 26 ++- .../observability/server/types/schema/slo.ts | 18 +- 20 files changed, 1135 insertions(+), 38 deletions(-) create mode 100644 x-pack/plugins/observability/server/assets/transform_templates/slo_transform_template.ts create mode 100644 x-pack/plugins/observability/server/services/slo/fixtures/slo.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.test.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.test.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/index.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_generators/transform_generator.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_installer.test.ts create mode 100644 x-pack/plugins/observability/server/services/slo/transform_installer.ts diff --git a/x-pack/plugins/observability/server/assets/constants.ts b/x-pack/plugins/observability/server/assets/constants.ts index 09d22022caffd0..8afa22d5f695ee 100644 --- a/x-pack/plugins/observability/server/assets/constants.ts +++ b/x-pack/plugins/observability/server/assets/constants.ts @@ -7,6 +7,9 @@ export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = 'observability-slo-mappings'; export const SLO_COMPONENT_TEMPLATE_SETTINGS_NAME = 'observability-slo-settings'; -export const SLO_INDEX_TEMPLATE_NAME = 'observability-slo-data'; +export const SLO_INDEX_TEMPLATE_NAME = 'slo-observability.sli'; export const SLO_INGEST_PIPELINE_NAME = 'observability-slo-monthly-index'; export const SLO_RESOURCES_VERSION = 1; + +export const getSLODestinationIndexName = (spaceId: string) => + `${SLO_INDEX_TEMPLATE_NAME}-v${SLO_RESOURCES_VERSION}-${spaceId}`; diff --git a/x-pack/plugins/observability/server/assets/transform_templates/slo_transform_template.ts b/x-pack/plugins/observability/server/assets/transform_templates/slo_transform_template.ts new file mode 100644 index 00000000000000..6b313bdb76c5ab --- /dev/null +++ b/x-pack/plugins/observability/server/assets/transform_templates/slo_transform_template.ts @@ -0,0 +1,42 @@ +/* + * 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 { + TransformDestination, + TransformPivot, + TransformPutTransformRequest, + TransformSource, +} from '@elastic/elasticsearch/lib/api/types'; + +export const getSLOTransformTemplate = ( + transformId: string, + source: TransformSource, + destination: TransformDestination, + groupBy: TransformPivot['group_by'] = {}, + aggregations: TransformPivot['aggregations'] = {} +): TransformPutTransformRequest => ({ + transform_id: transformId, + source, + frequency: '1m', + dest: destination, + settings: { + deduce_mappings: false, + }, + sync: { + time: { + field: '@timestamp', + delay: '60s', + }, + }, + pivot: { + group_by: groupBy, + aggregations, + }, + _meta: { + version: 1, + }, +}); diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts index 5b47bbead83006..4a1f91719bca64 100644 --- a/x-pack/plugins/observability/server/plugin.ts +++ b/x-pack/plugins/observability/server/plugin.ts @@ -145,7 +145,6 @@ export class ObservabilityPlugin implements Plugin { const start = () => core.getStartServices().then(([coreStart]) => coreStart); const { spacesService } = plugins.spaces; - const { ruleDataService } = plugins.ruleRegistry; registerRoutes({ diff --git a/x-pack/plugins/observability/server/routes/slo/route.ts b/x-pack/plugins/observability/server/routes/slo/route.ts index e868bc99a54175..c5b2e7d1030e62 100644 --- a/x-pack/plugins/observability/server/routes/slo/route.ts +++ b/x-pack/plugins/observability/server/routes/slo/route.ts @@ -5,6 +5,17 @@ * 2.0. */ +import uuid from 'uuid'; +import { + KibanaSavedObjectsSLORepository, + ResourceInstaller, + TransformInstaller, +} from '../../services/slo'; +import { + ApmTransactionDurationTransformGenerator, + ApmTransactionErrorRateTransformGenerator, +} from '../../services/slo/transform_generators'; +import { SLO } from '../../types/models'; import { createSLOParamsSchema } from '../../types/schema'; import { createObservabilityServerRoute } from '../create_observability_server_route'; @@ -14,8 +25,36 @@ const createSLORoute = createObservabilityServerRoute({ tags: [], }, params: createSLOParamsSchema, - handler: async ({ context, request, params }) => { - return { success: true }; + handler: async ({ context, request, params, logger, spacesService }) => { + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const soClient = (await context.core).savedObjects.client; + const spaceId = spacesService.getSpaceId(request); + + const resourceInstaller = new ResourceInstaller(esClient, logger); + const repository = new KibanaSavedObjectsSLORepository(soClient); + const transformInstaller = new TransformInstaller( + { + 'slo.apm.transaction_duration': new ApmTransactionDurationTransformGenerator(), + 'slo.apm.transaction_error_rate': new ApmTransactionErrorRateTransformGenerator(), + }, + esClient, + logger + ); + + await resourceInstaller.ensureCommonResourcesInstalled(spaceId); + + const slo: SLO = { + ...params.body, + id: uuid.v1(), + settings: { + destination_index: params.body.settings?.destination_index, + }, + }; + + await repository.save(slo); + await transformInstaller.installAndStartTransform(slo, spaceId); + + return slo; }, }); diff --git a/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts new file mode 100644 index 00000000000000..c6bdb2c5a1e77a --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts @@ -0,0 +1,51 @@ +/* + * 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 uuid from 'uuid'; +import { SLI, SLO } from '../../../types/models'; + +export const createSLO = (indicator: SLI): SLO => ({ + id: uuid.v1(), + name: 'irrelevant', + description: 'irrelevant', + indicator, + time_window: { + duration: '7d', + is_rolling: true, + }, + budgeting_method: 'occurrences', + objective: { + target: 0.999, + }, + settings: { + destination_index: 'some-index', + }, +}); + +export const createAPMTransactionErrorRateIndicator = (params = {}): SLI => ({ + type: 'slo.apm.transaction_error_rate', + params: { + environment: 'irrelevant', + service: 'irrelevant', + transaction_name: 'irrelevant', + transaction_type: 'irrelevant', + good_status_codes: ['2xx', '3xx', '4xx'], + ...params, + }, +}); + +export const createAPMTransactionDurationIndicator = (params = {}): SLI => ({ + type: 'slo.apm.transaction_duration', + params: { + environment: 'irrelevant', + service: 'irrelevant', + transaction_name: 'irrelevant', + transaction_type: 'irrelevant', + 'threshold.us': 500000, + ...params, + }, +}); diff --git a/x-pack/plugins/observability/server/services/slo/index.ts b/x-pack/plugins/observability/server/services/slo/index.ts index 39c288bbbf5393..d6b7d96fc112bd 100644 --- a/x-pack/plugins/observability/server/services/slo/index.ts +++ b/x-pack/plugins/observability/server/services/slo/index.ts @@ -7,3 +7,4 @@ export * from './resource_installer'; export * from './slo_repository'; +export * from './transform_installer'; diff --git a/x-pack/plugins/observability/server/services/slo/resource_installer.ts b/x-pack/plugins/observability/server/services/slo/resource_installer.ts index 92ea496e256df3..81b2a0e0eb4577 100644 --- a/x-pack/plugins/observability/server/services/slo/resource_installer.ts +++ b/x-pack/plugins/observability/server/services/slo/resource_installer.ts @@ -67,7 +67,9 @@ export class ResourceInstaller { } private getPipelinePrefix(version: number, spaceId: string): string { - return `${SLO_INDEX_TEMPLATE_NAME}-version-${version}-${spaceId}-`; + // Following https://www.elastic.co/blog/an-introduction-to-the-elastic-data-stream-naming-scheme + // slo-observability.sli--. + return `${SLO_INDEX_TEMPLATE_NAME}-v${version}-${spaceId}.`; } private async areResourcesAlreadyInstalled(): Promise { diff --git a/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts b/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts index 8e7b7bbcac4277..265cc355860d98 100644 --- a/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts +++ b/x-pack/plugins/observability/server/services/slo/slo_repository.test.ts @@ -5,7 +5,6 @@ * 2.0. */ -import uuid from 'uuid'; import { SavedObject } from '@kbn/core-saved-objects-common'; import { SavedObjectsClientContract } from '@kbn/core/server'; import { savedObjectsClientMock } from '@kbn/core/server/mocks'; @@ -13,33 +12,18 @@ import { savedObjectsClientMock } from '@kbn/core/server/mocks'; import { SLO, StoredSLO } from '../../types/models'; import { SO_SLO_TYPE } from '../../saved_objects'; import { KibanaSavedObjectsSLORepository } from './slo_repository'; +import { createSLO } from './fixtures/slo'; -const anSLO: SLO = { - id: uuid.v1(), - name: 'irrelevant', - description: 'irrelevant', - indicator: { - type: 'slo.apm.transaction_duration', - params: { - environment: 'irrelevant', - service: 'irrelevant', - transaction_type: 'irrelevant', - transaction_name: 'irrelevant', - 'threshold.us': 200000, - }, - }, - time_window: { - duration: '7d', - is_rolling: true, - }, - budgeting_method: 'occurrences', - objective: { - target: 0.999, +const anSLO = createSLO({ + type: 'slo.apm.transaction_duration', + params: { + environment: 'irrelevant', + service: 'irrelevant', + transaction_type: 'irrelevant', + transaction_name: 'irrelevant', + 'threshold.us': 200000, }, - settings: { - destination_index: 'some-index', - }, -}; +}); function aStoredSLO(slo: SLO): SavedObject { return { diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap new file mode 100644 index 00000000000000..ade6f8b90d8949 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_duration.test.ts.snap @@ -0,0 +1,139 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`APM Transaction Duration Transform Generator does not include the query filter when params are 'ALL' 1`] = ` +Object { + "bool": Object { + "filter": Array [ + Object { + "match": Object { + "transaction.root": true, + }, + }, + ], + }, +} +`; + +exports[`APM Transaction Duration Transform Generator returns the correct transform params with every specified indicator params 1`] = ` +Object { + "_meta": Object { + "version": 1, + }, + "dest": Object { + "index": "some-index", + }, + "frequency": "1m", + "pivot": Object { + "aggregations": Object { + "_numerator": Object { + "range": Object { + "field": "transaction.duration.histogram", + "ranges": Array [ + Object { + "to": 500000, + }, + ], + }, + }, + "slo.denominator": Object { + "value_count": Object { + "field": "transaction.duration.histogram", + }, + }, + "slo.numerator": Object { + "bucket_script": Object { + "buckets_path": Object { + "numerator": "_numerator['*-500000.0']>_count", + }, + "script": "params.numerator", + }, + }, + }, + "group_by": Object { + "@timestamp": Object { + "date_histogram": Object { + "calendar_interval": "1m", + "field": "@timestamp", + }, + }, + "slo.context.service.environment": Object { + "terms": Object { + "field": "service.environment", + }, + }, + "slo.context.service.name": Object { + "terms": Object { + "field": "service.name", + }, + }, + "slo.context.transaction.name": Object { + "terms": Object { + "field": "transaction.name", + }, + }, + "slo.context.transaction.type": Object { + "terms": Object { + "field": "transaction.type", + }, + }, + "slo.id": Object { + "terms": Object { + "field": "slo.id", + }, + }, + }, + }, + "settings": Object { + "deduce_mappings": false, + }, + "source": Object { + "index": "metrics-apm*", + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "match": Object { + "transaction.root": true, + }, + }, + Object { + "match": Object { + "service.name": "irrelevant", + }, + }, + Object { + "match": Object { + "service.environment": "irrelevant", + }, + }, + Object { + "match": Object { + "transaction.name": "irrelevant", + }, + }, + Object { + "match": Object { + "transaction.type": "irrelevant", + }, + }, + ], + }, + }, + "runtime_mappings": Object { + "slo.id": Object { + "script": Object { + "source": Any, + }, + "type": "keyword", + }, + }, + }, + "sync": Object { + "time": Object { + "delay": "60s", + "field": "@timestamp", + }, + }, + "transform_id": Any, +} +`; diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap new file mode 100644 index 00000000000000..d07a06e0724cf3 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/__snapshots__/apm_transaction_error_rate.test.ts.snap @@ -0,0 +1,177 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`APM Transaction Error Rate Transform Generator does not include the query filter when params are 'ALL' 1`] = ` +Object { + "bool": Object { + "filter": Array [ + Object { + "match": Object { + "transaction.root": true, + }, + }, + ], + }, +} +`; + +exports[`APM Transaction Error Rate Transform Generator returns the correct transform params with every specified indicator params 1`] = ` +Object { + "_meta": Object { + "version": 1, + }, + "dest": Object { + "index": "some-index", + }, + "frequency": "1m", + "pivot": Object { + "aggregations": Object { + "slo.denominator": Object { + "value_count": Object { + "field": "transaction.duration.histogram", + }, + }, + "slo.numerator": Object { + "filter": Object { + "bool": Object { + "should": Array [ + Object { + "match": Object { + "transaction.result": "HTTP 2xx", + }, + }, + Object { + "match": Object { + "transaction.result": "HTTP 3xx", + }, + }, + Object { + "match": Object { + "transaction.result": "HTTP 4xx", + }, + }, + ], + }, + }, + }, + }, + "group_by": Object { + "@timestamp": Object { + "date_histogram": Object { + "calendar_interval": "1m", + "field": "@timestamp", + }, + }, + "slo.context.service.environment": Object { + "terms": Object { + "field": "service.environment", + }, + }, + "slo.context.service.name": Object { + "terms": Object { + "field": "service.name", + }, + }, + "slo.context.transaction.name": Object { + "terms": Object { + "field": "transaction.name", + }, + }, + "slo.context.transaction.type": Object { + "terms": Object { + "field": "transaction.type", + }, + }, + "slo.id": Object { + "terms": Object { + "field": "slo.id", + }, + }, + }, + }, + "settings": Object { + "deduce_mappings": false, + }, + "source": Object { + "index": "metrics-apm*", + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "match": Object { + "transaction.root": true, + }, + }, + Object { + "match": Object { + "service.name": "irrelevant", + }, + }, + Object { + "match": Object { + "service.environment": "irrelevant", + }, + }, + Object { + "match": Object { + "transaction.name": "irrelevant", + }, + }, + Object { + "match": Object { + "transaction.type": "irrelevant", + }, + }, + ], + }, + }, + "runtime_mappings": Object { + "slo.id": Object { + "script": Object { + "source": Any, + }, + "type": "keyword", + }, + }, + }, + "sync": Object { + "time": Object { + "delay": "60s", + "field": "@timestamp", + }, + }, + "transform_id": Any, +} +`; + +exports[`APM Transaction Error Rate Transform Generator uses default values when 'good_status_codes' is not specified 1`] = ` +Object { + "slo.denominator": Object { + "value_count": Object { + "field": "transaction.duration.histogram", + }, + }, + "slo.numerator": Object { + "filter": Object { + "bool": Object { + "should": Array [ + Object { + "match": Object { + "transaction.result": "HTTP 2xx", + }, + }, + Object { + "match": Object { + "transaction.result": "HTTP 3xx", + }, + }, + Object { + "match": Object { + "transaction.result": "HTTP 4xx", + }, + }, + ], + }, + }, + }, +} +`; diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.test.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.test.ts new file mode 100644 index 00000000000000..1671e11d4cf2a0 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.test.ts @@ -0,0 +1,41 @@ +/* + * 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 { createAPMTransactionDurationIndicator, createSLO } from '../fixtures/slo'; +import { ApmTransactionDurationTransformGenerator } from './apm_transaction_duration'; + +const generator = new ApmTransactionDurationTransformGenerator(); + +describe('APM Transaction Duration Transform Generator', () => { + it('returns the correct transform params with every specified indicator params', async () => { + const anSLO = createSLO(createAPMTransactionDurationIndicator()); + const transform = generator.getTransformParams(anSLO, 'my-namespace'); + + expect(transform).toMatchSnapshot({ + transform_id: expect.any(String), + source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } }, + }); + expect(transform.transform_id).toEqual(`slo-${anSLO.id}`); + expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({ + script: { source: `emit('${anSLO.id}')` }, + }); + }); + + it("does not include the query filter when params are 'ALL'", async () => { + const anSLO = createSLO( + createAPMTransactionDurationIndicator({ + environment: 'ALL', + service: 'ALL', + transaction_name: 'ALL', + transaction_type: 'ALL', + }) + ); + const transform = generator.getTransformParams(anSLO, 'my-namespace'); + + expect(transform.source.query).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts new file mode 100644 index 00000000000000..c00ba8f69d8059 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_duration.ts @@ -0,0 +1,179 @@ +/* + * 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 { + AggregationsCalendarInterval, + MappingRuntimeFieldType, + TransformPutTransformRequest, +} from '@elastic/elasticsearch/lib/api/types'; +import { getSLODestinationIndexName, SLO_INGEST_PIPELINE_NAME } from '../../../assets/constants'; +import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; +import { + SLO, + apmTransactionDurationSLOSchema, + APMTransactionDurationSLO, +} from '../../../types/models'; +import { ALL_VALUE } from '../../../types/schema'; +import { TransformGenerator } from '.'; + +const APM_SOURCE_INDEX = 'metrics-apm*'; + +export class ApmTransactionDurationTransformGenerator implements TransformGenerator { + public getTransformParams(slo: SLO, spaceId: string): TransformPutTransformRequest { + if (!apmTransactionDurationSLOSchema.is(slo)) { + throw new Error(`Cannot handle SLO of indicator type: ${slo.indicator.type}`); + } + + return getSLOTransformTemplate( + this.buildTransformId(slo), + this.buildSource(slo), + this.buildDestination(slo, spaceId), + this.buildGroupBy(), + this.buildAggregations(slo) + ); + } + + private buildTransformId(slo: APMTransactionDurationSLO): string { + return `slo-${slo.id}`; + } + + private buildSource(slo: APMTransactionDurationSLO) { + const queryFilter = []; + if (slo.indicator.params.service !== ALL_VALUE) { + queryFilter.push({ + match: { + 'service.name': slo.indicator.params.service, + }, + }); + } + + if (slo.indicator.params.environment !== ALL_VALUE) { + queryFilter.push({ + match: { + 'service.environment': slo.indicator.params.environment, + }, + }); + } + + if (slo.indicator.params.transaction_name !== ALL_VALUE) { + queryFilter.push({ + match: { + 'transaction.name': slo.indicator.params.transaction_name, + }, + }); + } + + if (slo.indicator.params.transaction_type !== ALL_VALUE) { + queryFilter.push({ + match: { + 'transaction.type': slo.indicator.params.transaction_type, + }, + }); + } + + return { + index: APM_SOURCE_INDEX, + runtime_mappings: { + 'slo.id': { + type: 'keyword' as MappingRuntimeFieldType, + script: { + source: `emit('${slo.id}')`, + }, + }, + }, + query: { + bool: { + filter: [ + { + match: { + 'transaction.root': true, + }, + }, + ...queryFilter, + ], + }, + }, + }; + } + + private buildDestination(slo: APMTransactionDurationSLO, spaceId: string) { + if (slo.settings.destination_index === undefined) { + return { + pipeline: SLO_INGEST_PIPELINE_NAME, + index: getSLODestinationIndexName(spaceId), + }; + } + + return { index: slo.settings.destination_index }; + } + + private buildGroupBy() { + return { + 'slo.id': { + terms: { + field: 'slo.id', + }, + }, + '@timestamp': { + date_histogram: { + field: '@timestamp', + calendar_interval: '1m' as AggregationsCalendarInterval, + }, + }, + 'slo.context.transaction.name': { + terms: { + field: 'transaction.name', + }, + }, + 'slo.context.transaction.type': { + terms: { + field: 'transaction.type', + }, + }, + 'slo.context.service.name': { + terms: { + field: 'service.name', + }, + }, + 'slo.context.service.environment': { + terms: { + field: 'service.environment', + }, + }, + }; + } + + private buildAggregations(slo: APMTransactionDurationSLO) { + const truncatedThreshold = Math.trunc(slo.indicator.params['threshold.us']); + + return { + _numerator: { + range: { + field: 'transaction.duration.histogram', + ranges: [ + { + to: truncatedThreshold, + }, + ], + }, + }, + 'slo.numerator': { + bucket_script: { + buckets_path: { + numerator: `_numerator['*-${truncatedThreshold}.0']>_count`, + }, + script: 'params.numerator', + }, + }, + 'slo.denominator': { + value_count: { + field: 'transaction.duration.histogram', + }, + }, + }; + } +} diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.test.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.test.ts new file mode 100644 index 00000000000000..0e9fb14f85468a --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.test.ts @@ -0,0 +1,48 @@ +/* + * 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 { createAPMTransactionErrorRateIndicator, createSLO } from '../fixtures/slo'; +import { ApmTransactionErrorRateTransformGenerator } from './apm_transaction_error_rate'; + +const generator = new ApmTransactionErrorRateTransformGenerator(); + +describe('APM Transaction Error Rate Transform Generator', () => { + it('returns the correct transform params with every specified indicator params', async () => { + const anSLO = createSLO(createAPMTransactionErrorRateIndicator()); + const transform = generator.getTransformParams(anSLO, 'my-namespace'); + + expect(transform).toMatchSnapshot({ + transform_id: expect.any(String), + source: { runtime_mappings: { 'slo.id': { script: { source: expect.any(String) } } } }, + }); + expect(transform.transform_id).toEqual(`slo-${anSLO.id}`); + expect(transform.source.runtime_mappings!['slo.id']).toMatchObject({ + script: { source: `emit('${anSLO.id}')` }, + }); + }); + + it("uses default values when 'good_status_codes' is not specified", async () => { + const anSLO = createSLO(createAPMTransactionErrorRateIndicator({ good_status_codes: [] })); + const transform = generator.getTransformParams(anSLO, 'my-namespace'); + + expect(transform.pivot?.aggregations).toMatchSnapshot(); + }); + + it("does not include the query filter when params are 'ALL'", async () => { + const anSLO = createSLO( + createAPMTransactionErrorRateIndicator({ + environment: 'ALL', + service: 'ALL', + transaction_name: 'ALL', + transaction_type: 'ALL', + }) + ); + const transform = generator.getTransformParams(anSLO, 'my-namespace'); + + expect(transform.source.query).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts new file mode 100644 index 00000000000000..c66de8913b6ef4 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/apm_transaction_error_rate.ts @@ -0,0 +1,185 @@ +/* + * 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 { + AggregationsCalendarInterval, + MappingRuntimeFieldType, + TransformPutTransformRequest, +} from '@elastic/elasticsearch/lib/api/types'; +import { getSLODestinationIndexName, SLO_INGEST_PIPELINE_NAME } from '../../../assets/constants'; +import { getSLOTransformTemplate } from '../../../assets/transform_templates/slo_transform_template'; +import { + apmTransactionErrorRateSLOSchema, + APMTransactionErrorRateSLO, + SLO, +} from '../../../types/models'; +import { ALL_VALUE } from '../../../types/schema'; +import { TransformGenerator } from '.'; + +const APM_SOURCE_INDEX = 'metrics-apm*'; +const ALLOWED_STATUS_CODES = ['2xx', '3xx', '4xx', '5xx']; +const DEFAULT_GOOD_STATUS_CODES = ['2xx', '3xx', '4xx']; + +export class ApmTransactionErrorRateTransformGenerator implements TransformGenerator { + public getTransformParams(slo: SLO, spaceId: string): TransformPutTransformRequest { + if (!apmTransactionErrorRateSLOSchema.is(slo)) { + throw new Error(`Cannot handle SLO of indicator type: ${slo.indicator.type}`); + } + + return getSLOTransformTemplate( + this.buildTransformId(slo), + this.buildSource(slo), + this.buildDestination(slo, spaceId), + this.buildGroupBy(), + this.buildAggregations(slo) + ); + } + + private buildTransformId(slo: APMTransactionErrorRateSLO): string { + return `slo-${slo.id}`; + } + + private buildSource(slo: APMTransactionErrorRateSLO) { + const queryFilter = []; + if (slo.indicator.params.service !== ALL_VALUE) { + queryFilter.push({ + match: { + 'service.name': slo.indicator.params.service, + }, + }); + } + + if (slo.indicator.params.environment !== ALL_VALUE) { + queryFilter.push({ + match: { + 'service.environment': slo.indicator.params.environment, + }, + }); + } + + if (slo.indicator.params.transaction_name !== ALL_VALUE) { + queryFilter.push({ + match: { + 'transaction.name': slo.indicator.params.transaction_name, + }, + }); + } + + if (slo.indicator.params.transaction_type !== ALL_VALUE) { + queryFilter.push({ + match: { + 'transaction.type': slo.indicator.params.transaction_type, + }, + }); + } + + return { + index: APM_SOURCE_INDEX, + runtime_mappings: { + 'slo.id': { + type: 'keyword' as MappingRuntimeFieldType, + script: { + source: `emit('${slo.id}')`, + }, + }, + }, + query: { + bool: { + filter: [ + { + match: { + 'transaction.root': true, + }, + }, + ...queryFilter, + ], + }, + }, + }; + } + + private buildDestination(slo: APMTransactionErrorRateSLO, spaceId: string) { + if (slo.settings.destination_index === undefined) { + return { + pipeline: SLO_INGEST_PIPELINE_NAME, + index: getSLODestinationIndexName(spaceId), + }; + } + + return { index: slo.settings.destination_index }; + } + + private buildGroupBy() { + return { + 'slo.id': { + terms: { + field: 'slo.id', + }, + }, + '@timestamp': { + date_histogram: { + field: '@timestamp', + calendar_interval: '1m' as AggregationsCalendarInterval, + }, + }, + 'slo.context.transaction.name': { + terms: { + field: 'transaction.name', + }, + }, + 'slo.context.transaction.type': { + terms: { + field: 'transaction.type', + }, + }, + 'slo.context.service.name': { + terms: { + field: 'service.name', + }, + }, + 'slo.context.service.environment': { + terms: { + field: 'service.environment', + }, + }, + }; + } + + private buildAggregations(slo: APMTransactionErrorRateSLO) { + const goodStatusCodesFilter = this.getGoodStatusCodesFilter( + slo.indicator.params.good_status_codes + ); + + return { + 'slo.numerator': { + filter: { + bool: { + should: goodStatusCodesFilter, + }, + }, + }, + 'slo.denominator': { + value_count: { + field: 'transaction.duration.histogram', + }, + }, + }; + } + + private getGoodStatusCodesFilter(goodStatusCodes: string[] | undefined) { + let statusCodes = goodStatusCodes?.filter((code) => ALLOWED_STATUS_CODES.includes(code)); + if (statusCodes === undefined || statusCodes.length === 0) { + statusCodes = DEFAULT_GOOD_STATUS_CODES; + } + + return statusCodes.map((code) => ({ + match: { + 'transaction.result': `HTTP ${code}`, + }, + })); + } +} diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/index.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/index.ts new file mode 100644 index 00000000000000..6f0484c2044ada --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/index.ts @@ -0,0 +1,10 @@ +/* + * 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 './transform_generator'; +export * from './apm_transaction_error_rate'; +export * from './apm_transaction_duration'; diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/transform_generator.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/transform_generator.ts new file mode 100644 index 00000000000000..21a917ea1af6d1 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/transform_generator.ts @@ -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. + */ + +import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SLO } from '../../../types/models'; + +export interface TransformGenerator { + getTransformParams(slo: SLO, spaceId: string): TransformPutTransformRequest; +} diff --git a/x-pack/plugins/observability/server/services/slo/transform_installer.test.ts b/x-pack/plugins/observability/server/services/slo/transform_installer.test.ts new file mode 100644 index 00000000000000..cc65aac74c32eb --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_installer.test.ts @@ -0,0 +1,102 @@ +/* + * 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. + */ +/* eslint-disable max-classes-per-file */ + +import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { ElasticsearchClient } from '@kbn/core/server'; +import { MockedLogger } from '@kbn/logging-mocks'; +import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types'; + +import { TransformInstaller } from './transform_installer'; +import { + ApmTransactionErrorRateTransformGenerator, + TransformGenerator, +} from './transform_generators'; +import { SLO, SLITypes } from '../../types/models'; +import { createAPMTransactionErrorRateIndicator, createSLO } from './fixtures/slo'; + +describe('TransformerGenerator', () => { + let esClientMock: jest.Mocked; + let loggerMock: jest.Mocked; + + beforeEach(() => { + esClientMock = elasticsearchServiceMock.createElasticsearchClient(); + loggerMock = loggingSystemMock.createLogger(); + }); + + describe('Unhappy path', () => { + it('throws when no generator exists for the slo indicator type', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_duration': new DummyTransformGenerator(), + }; + const service = new TransformInstaller(generators, esClientMock, loggerMock); + + expect(() => + service.installAndStartTransform( + createSLO({ + type: 'slo.apm.transaction_error_rate', + params: { + environment: 'irrelevant', + service: 'irrelevant', + transaction_name: 'irrelevant', + transaction_type: 'irrelevant', + }, + }) + ) + ).rejects.toThrowError('Unsupported SLO type: slo.apm.transaction_error_rate'); + }); + + it('throws when transform generator fails', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_duration': new FailTransformGenerator(), + }; + const service = new TransformInstaller(generators, esClientMock, loggerMock); + + expect(() => + service.installAndStartTransform( + createSLO({ + type: 'slo.apm.transaction_duration', + params: { + environment: 'irrelevant', + service: 'irrelevant', + transaction_name: 'irrelevant', + transaction_type: 'irrelevant', + 'threshold.us': 250000, + }, + }) + ) + ).rejects.toThrowError('Some error'); + }); + }); + + it('installs and starts the transform', async () => { + // @ts-ignore defining only a subset of the possible SLI + const generators: Record = { + 'slo.apm.transaction_error_rate': new ApmTransactionErrorRateTransformGenerator(), + }; + const service = new TransformInstaller(generators, esClientMock, loggerMock); + + await service.installAndStartTransform(createSLO(createAPMTransactionErrorRateIndicator())); + + expect(esClientMock.transform.putTransform).toHaveBeenCalledTimes(1); + expect(esClientMock.transform.startTransform).toHaveBeenCalledTimes(1); + }); +}); + +class DummyTransformGenerator implements TransformGenerator { + getTransformParams(slo: SLO): TransformPutTransformRequest { + return {} as TransformPutTransformRequest; + } +} + +class FailTransformGenerator implements TransformGenerator { + getTransformParams(slo: SLO): TransformPutTransformRequest { + throw new Error('Some error'); + } +} diff --git a/x-pack/plugins/observability/server/services/slo/transform_installer.ts b/x-pack/plugins/observability/server/services/slo/transform_installer.ts new file mode 100644 index 00000000000000..cd677e10491ca5 --- /dev/null +++ b/x-pack/plugins/observability/server/services/slo/transform_installer.ts @@ -0,0 +1,52 @@ +/* + * 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 { errors } from '@elastic/elasticsearch'; + +import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { SLO, SLITypes } from '../../types/models'; +import { TransformGenerator } from './transform_generators'; + +export class TransformInstaller { + constructor( + private generators: Record, + private esClient: ElasticsearchClient, + private logger: Logger + ) {} + + async installAndStartTransform(slo: SLO, spaceId: string = 'default'): Promise { + const generator = this.generators[slo.indicator.type]; + if (!generator) { + this.logger.error(`No transform generator found for ${slo.indicator.type} SLO type`); + throw new Error(`Unsupported SLO type: ${slo.indicator.type}`); + } + + const transformParams = generator.getTransformParams(slo, spaceId); + try { + await this.esClient.transform.putTransform(transformParams); + } catch (err) { + // swallow the error if the transform already exists. + const isAlreadyExistError = + err instanceof errors.ResponseError && + err?.body?.error?.type === 'resource_already_exists_exception'; + if (!isAlreadyExistError) { + this.logger.error(`Cannot create transform for ${slo.indicator.type} SLO type: ${err}`); + throw err; + } + } + + try { + await this.esClient.transform.startTransform( + { transform_id: transformParams.transform_id }, + { ignore: [409] } + ); + } catch (err) { + this.logger.error(`Cannot start transform id ${transformParams.transform_id}: ${err}`); + throw err; + } + } +} diff --git a/x-pack/plugins/observability/server/types/models/slo.ts b/x-pack/plugins/observability/server/types/models/slo.ts index 94017b50eb65a1..0cbb60531cc362 100644 --- a/x-pack/plugins/observability/server/types/models/slo.ts +++ b/x-pack/plugins/observability/server/types/models/slo.ts @@ -7,14 +7,20 @@ import * as t from 'io-ts'; -import { indicatorSchema, rollingTimeWindowSchema } from '../schema'; +import { + apmTransactionDurationIndicatorSchema, + apmTransactionErrorRateIndicatorSchema, + indicatorSchema, + indicatorTypesSchema, + rollingTimeWindowSchema, +} from '../schema'; const baseSLOSchema = t.type({ id: t.string, name: t.string, description: t.string, - indicator: indicatorSchema, time_window: rollingTimeWindowSchema, + indicator: indicatorSchema, budgeting_method: t.literal('occurrences'), objective: t.type({ target: t.number, @@ -24,10 +30,26 @@ const baseSLOSchema = t.type({ }), }); +export const apmTransactionErrorRateSLOSchema = t.intersection([ + baseSLOSchema, + t.type({ indicator: apmTransactionErrorRateIndicatorSchema }), +]); + +export const apmTransactionDurationSLOSchema = t.intersection([ + baseSLOSchema, + t.type({ indicator: apmTransactionDurationIndicatorSchema }), +]); + const storedSLOSchema = t.intersection([ baseSLOSchema, t.type({ created_at: t.string, updated_at: t.string }), ]); export type SLO = t.TypeOf; +export type APMTransactionErrorRateSLO = t.TypeOf; +export type APMTransactionDurationSLO = t.TypeOf; + +export type SLI = t.TypeOf; +export type SLITypes = t.TypeOf; + export type StoredSLO = t.TypeOf; diff --git a/x-pack/plugins/observability/server/types/schema/slo.ts b/x-pack/plugins/observability/server/types/schema/slo.ts index 62495ff26d4f49..2896e443e2c37c 100644 --- a/x-pack/plugins/observability/server/types/schema/slo.ts +++ b/x-pack/plugins/observability/server/types/schema/slo.ts @@ -7,10 +7,12 @@ import * as t from 'io-ts'; -const allOrAnyString = t.union([t.literal('ALL'), t.string]); +export const ALL_VALUE = 'ALL'; +const allOrAnyString = t.union([t.literal(ALL_VALUE), t.string]); -const apmTransactionDurationIndicatorSchema = t.type({ - type: t.literal('slo.apm.transaction_duration'), +const apmTransactionDurationIndicatorTypeSchema = t.literal('slo.apm.transaction_duration'); +export const apmTransactionDurationIndicatorSchema = t.type({ + type: apmTransactionDurationIndicatorTypeSchema, params: t.type({ environment: allOrAnyString, service: allOrAnyString, @@ -20,8 +22,9 @@ const apmTransactionDurationIndicatorSchema = t.type({ }), }); -const apmTransactionErrorRateIndicatorSchema = t.type({ - type: t.literal('slo.apm.transaction_error_rate'), +const apmTransactionErrorRateIndicatorTypeSchema = t.literal('slo.apm.transaction_error_rate'); +export const apmTransactionErrorRateIndicatorSchema = t.type({ + type: apmTransactionErrorRateIndicatorTypeSchema, params: t.intersection([ t.type({ environment: allOrAnyString, @@ -42,6 +45,11 @@ export const rollingTimeWindowSchema = t.type({ is_rolling: t.literal(true), }); +export const indicatorTypesSchema = t.union([ + apmTransactionDurationIndicatorTypeSchema, + apmTransactionErrorRateIndicatorTypeSchema, +]); + export const indicatorSchema = t.union([ apmTransactionDurationIndicatorSchema, apmTransactionErrorRateIndicatorSchema, From f2b1f811989809fbfdbf0d66138d5b3b726d9f5b Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Fri, 9 Sep 2022 19:22:17 +0200 Subject: [PATCH 025/144] [Security Solution][Endpoint][Response Actions] Action history page under security->manage (#140306) * Action history page under security->manage fixes elastic/security-team/issues/4902 * update test snapshot fixes elastic/security-team/issues/4902 * update icon fixes elastic/security-team/issues/4902 --- .../security_solution/common/constants.ts | 6 +-- .../public/app/deep_links/index.ts | 14 +++---- .../public/app/home/home_navigations.ts | 10 ++--- .../public/app/translations.ts | 9 ++--- .../common/components/navigation/types.ts | 2 +- .../__snapshots__/index.test.tsx.snap | 10 +++++ .../use_navigation_items.tsx | 1 + .../public/management/common/breadcrumbs.ts | 4 +- .../public/management/common/constants.ts | 2 +- .../translations.tsx | 4 +- .../management/icons/action_history.tsx | 37 +++++++++++++++++++ .../public/management/links.ts | 15 ++++++++ .../public/management/pages/index.tsx | 8 ++-- .../pages/response_actions/index.tsx | 4 +- .../view/response_actions_list_page.tsx | 7 +++- .../public/management/types.ts | 2 +- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 19 files changed, 100 insertions(+), 41 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/icons/action_history.tsx diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index a59f57e45cdd0b..622c74efd82814 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -113,7 +113,7 @@ export enum SecurityPageName { noPage = '', overview = 'overview', policies = 'policy', - responseActions = 'response_actions', + actionHistory = 'action_history', rules = 'rules', rulesCreate = 'rules-create', sessions = 'sessions', @@ -159,7 +159,7 @@ export const EVENT_FILTERS_PATH = `${MANAGEMENT_PATH}/event_filters` as const; export const HOST_ISOLATION_EXCEPTIONS_PATH = `${MANAGEMENT_PATH}/host_isolation_exceptions` as const; export const BLOCKLIST_PATH = `${MANAGEMENT_PATH}/blocklist` as const; -export const RESPONSE_ACTIONS_PATH = `${MANAGEMENT_PATH}/response_actions` as const; +export const ACTION_HISTORY_PATH = `${MANAGEMENT_PATH}/action_history` as const; export const ENTITY_ANALYTICS_PATH = '/entity_analytics' as const; export const APP_OVERVIEW_PATH = `${APP_PATH}${OVERVIEW_PATH}` as const; export const APP_LANDING_PATH = `${APP_PATH}${LANDING_PATH}` as const; @@ -183,7 +183,7 @@ export const APP_EVENT_FILTERS_PATH = `${APP_PATH}${EVENT_FILTERS_PATH}` as cons export const APP_HOST_ISOLATION_EXCEPTIONS_PATH = `${APP_PATH}${HOST_ISOLATION_EXCEPTIONS_PATH}` as const; export const APP_BLOCKLIST_PATH = `${APP_PATH}${BLOCKLIST_PATH}` as const; -export const APP_RESPONSE_ACTIONS_PATH = `${APP_PATH}${RESPONSE_ACTIONS_PATH}` as const; +export const APP_ACTION_HISTORY_PATH = `${APP_PATH}${ACTION_HISTORY_PATH}` as const; export const APP_ENTITY_ANALYTICS_PATH = `${APP_PATH}${ENTITY_ANALYTICS_PATH}` as const; // cloud logs to exclude from default index pattern diff --git a/x-pack/plugins/security_solution/public/app/deep_links/index.ts b/x-pack/plugins/security_solution/public/app/deep_links/index.ts index 7dad742861ac0c..6ac3a0aa7a3ff9 100644 --- a/x-pack/plugins/security_solution/public/app/deep_links/index.ts +++ b/x-pack/plugins/security_solution/public/app/deep_links/index.ts @@ -42,7 +42,7 @@ import { NETWORK, OVERVIEW, POLICIES, - RESPONSE_ACTIONS, + ACTION_HISTORY, ENTITY_ANALYTICS, RULES, TIMELINES, @@ -65,7 +65,7 @@ import { NETWORK_PATH, OVERVIEW_PATH, POLICIES_PATH, - RESPONSE_ACTIONS_PATH, + ACTION_HISTORY_PATH, ENTITY_ANALYTICS_PATH, RULES_CREATE_PATH, RULES_PATH, @@ -514,13 +514,13 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ path: BLOCKLIST_PATH, }, { - ...getSecuritySolutionLink('benchmarks'), - deepLinks: [getSecuritySolutionLink('rules')], + id: SecurityPageName.actionHistory, + title: ACTION_HISTORY, + path: ACTION_HISTORY_PATH, }, { - id: SecurityPageName.responseActions, - title: RESPONSE_ACTIONS, - path: RESPONSE_ACTIONS_PATH, + ...getSecuritySolutionLink('benchmarks'), + deepLinks: [getSecuritySolutionLink('rules')], }, ], }, diff --git a/x-pack/plugins/security_solution/public/app/home/home_navigations.ts b/x-pack/plugins/security_solution/public/app/home/home_navigations.ts index 88ef1152b8f343..ae7c15c73a4d2f 100644 --- a/x-pack/plugins/security_solution/public/app/home/home_navigations.ts +++ b/x-pack/plugins/security_solution/public/app/home/home_navigations.ts @@ -30,7 +30,7 @@ import { APP_USERS_PATH, APP_KUBERNETES_PATH, APP_LANDING_PATH, - APP_RESPONSE_ACTIONS_PATH, + APP_ACTION_HISTORY_PATH, APP_ENTITY_ANALYTICS_PATH, APP_PATH, } from '../../../common/constants'; @@ -162,10 +162,10 @@ export const navTabs: SecurityNav = { disabled: false, urlKey: 'administration', }, - [SecurityPageName.responseActions]: { - id: SecurityPageName.responseActions, - name: i18n.RESPONSE_ACTIONS, - href: APP_RESPONSE_ACTIONS_PATH, + [SecurityPageName.actionHistory]: { + id: SecurityPageName.actionHistory, + name: i18n.ACTION_HISTORY, + href: APP_ACTION_HISTORY_PATH, disabled: false, urlKey: 'administration', }, diff --git a/x-pack/plugins/security_solution/public/app/translations.ts b/x-pack/plugins/security_solution/public/app/translations.ts index 400642bc1490d5..154127f469c961 100644 --- a/x-pack/plugins/security_solution/public/app/translations.ts +++ b/x-pack/plugins/security_solution/public/app/translations.ts @@ -120,12 +120,9 @@ export const BLOCKLIST = i18n.translate('xpack.securitySolution.navigation.block defaultMessage: 'Blocklist', }); -export const RESPONSE_ACTIONS = i18n.translate( - 'xpack.securitySolution.navigation.responseActions', - { - defaultMessage: 'Response Actions', - } -); +export const ACTION_HISTORY = i18n.translate('xpack.securitySolution.navigation.actionHistory', { + defaultMessage: 'Action history', +}); export const CREATE_NEW_RULE = i18n.translate('xpack.securitySolution.navigation.newRuleTitle', { defaultMessage: 'Create new rule', diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts index 99ce1198f30d76..5a4c346be2e12d 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts @@ -65,6 +65,7 @@ export interface NavTab { } export const securityNavKeys = [ SecurityPageName.alerts, + SecurityPageName.actionHistory, SecurityPageName.blocklist, SecurityPageName.detectionAndResponse, SecurityPageName.case, @@ -77,7 +78,6 @@ export const securityNavKeys = [ SecurityPageName.hosts, SecurityPageName.network, SecurityPageName.overview, - SecurityPageName.responseActions, SecurityPageName.rules, SecurityPageName.timelines, SecurityPageName.trustedApps, diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap index 3b87593d9f4831..a7f54ccf701b81 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/__snapshots__/index.test.tsx.snap @@ -240,6 +240,16 @@ Object { "name": "Blocklist", "onClick": [Function], }, + Object { + "data-href": "securitySolutionUI/action_history", + "data-test-subj": "navigation-action_history", + "disabled": false, + "href": "securitySolutionUI/action_history", + "id": "action_history", + "isSelected": false, + "name": "Action history", + "onClick": [Function], + }, Object { "data-href": "securitySolutionUI/cloud_security_posture-benchmarks", "data-test-subj": "navigation-cloud_security_posture-benchmarks", diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_navigation_items.tsx b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_navigation_items.tsx index ea1448e57398bc..2a8d977760cbfc 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_navigation_items.tsx +++ b/x-pack/plugins/security_solution/public/common/components/navigation/use_security_solution_navigation/use_navigation_items.tsx @@ -147,6 +147,7 @@ function usePrimaryNavigationItemsToDisplay(navTabs: Record) { ? [navTabs[SecurityPageName.hostIsolationExceptions]] : []), navTabs[SecurityPageName.blocklist], + navTabs[SecurityPageName.actionHistory], navTabs[SecurityPageName.cloudSecurityPostureBenchmarks], ], }, diff --git a/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts b/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts index bfeccafd2e977f..12dfa0f28208a3 100644 --- a/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts +++ b/x-pack/plugins/security_solution/public/management/common/breadcrumbs.ts @@ -9,7 +9,7 @@ import type { ChromeBreadcrumb } from '@kbn/core/public'; import { AdministrationSubTab } from '../types'; import { ENDPOINTS_TAB, EVENT_FILTERS_TAB, POLICIES_TAB, TRUSTED_APPS_TAB } from './translations'; import type { AdministrationRouteSpyState } from '../../common/utils/route/types'; -import { HOST_ISOLATION_EXCEPTIONS, BLOCKLIST, RESPONSE_ACTIONS } from '../../app/translations'; +import { HOST_ISOLATION_EXCEPTIONS, BLOCKLIST, ACTION_HISTORY } from '../../app/translations'; const TabNameMappedToI18nKey: Record = { [AdministrationSubTab.endpoints]: ENDPOINTS_TAB, @@ -18,7 +18,7 @@ const TabNameMappedToI18nKey: Record = { [AdministrationSubTab.eventFilters]: EVENT_FILTERS_TAB, [AdministrationSubTab.hostIsolationExceptions]: HOST_ISOLATION_EXCEPTIONS, [AdministrationSubTab.blocklist]: BLOCKLIST, - [AdministrationSubTab.responseActions]: RESPONSE_ACTIONS, + [AdministrationSubTab.actionHistory]: ACTION_HISTORY, }; export function getTrailingBreadcrumbs(params: AdministrationRouteSpyState): ChromeBreadcrumb[] { diff --git a/x-pack/plugins/security_solution/public/management/common/constants.ts b/x-pack/plugins/security_solution/public/management/common/constants.ts index a46a9d8a9397f3..afad5b78e9f4e6 100644 --- a/x-pack/plugins/security_solution/public/management/common/constants.ts +++ b/x-pack/plugins/security_solution/public/management/common/constants.ts @@ -23,7 +23,7 @@ export const MANAGEMENT_ROUTING_TRUSTED_APPS_PATH = `${MANAGEMENT_PATH}/:tabName export const MANAGEMENT_ROUTING_EVENT_FILTERS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.eventFilters})`; export const MANAGEMENT_ROUTING_HOST_ISOLATION_EXCEPTIONS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.hostIsolationExceptions})`; export const MANAGEMENT_ROUTING_BLOCKLIST_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.blocklist})`; -export const MANAGEMENT_ROUTING_RESPONSE_ACTIONS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.responseActions})`; +export const MANAGEMENT_ROUTING_ACTION_HISTORY_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.actionHistory})`; // --[ STORE ]--------------------------------------------------------------------------- /** The SIEM global store namespace where the management state will be mounted */ diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx index fc6d3f6e7349ec..f16feaeb944559 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx @@ -95,8 +95,8 @@ export const UX_MESSAGES = Object.freeze({ defaultMessage: `Actions log : {hostname}`, values: { hostname }, }), - pageTitle: i18n.translate('xpack.securitySolution.responseActionsList.list.title', { - defaultMessage: 'Response actions', + pageSubTitle: i18n.translate('xpack.securitySolution.responseActionsList.list.pageSubTitle', { + defaultMessage: 'View the history of response actions performed on hosts.', }), fetchError: i18n.translate('xpack.securitySolution.responseActionsList.list.errorMessage', { defaultMessage: 'Error while retrieving response actions', diff --git a/x-pack/plugins/security_solution/public/management/icons/action_history.tsx b/x-pack/plugins/security_solution/public/management/icons/action_history.tsx new file mode 100644 index 00000000000000..9a2763a2f338fb --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/icons/action_history.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 type { SVGProps } from 'react'; +import React from 'react'; +export const IconActionHistory: React.FC> = ({ ...props }) => ( + + + + + +); diff --git a/x-pack/plugins/security_solution/public/management/links.ts b/x-pack/plugins/security_solution/public/management/links.ts index 4f41f95d3a5568..659fb7a8216a51 100644 --- a/x-pack/plugins/security_solution/public/management/links.ts +++ b/x-pack/plugins/security_solution/public/management/links.ts @@ -16,6 +16,7 @@ import { HOST_ISOLATION_EXCEPTIONS_PATH, MANAGE_PATH, POLICIES_PATH, + ACTION_HISTORY_PATH, RULES_CREATE_PATH, RULES_PATH, SecurityPageName, @@ -31,6 +32,7 @@ import { HOST_ISOLATION_EXCEPTIONS, MANAGE, POLICIES, + ACTION_HISTORY, RULES, TRUSTED_APPLICATIONS, } from '../app/translations'; @@ -41,6 +43,7 @@ import { manageCategories as cloudSecurityPostureCategories, manageLinks as cloudSecurityPostureLinks, } from '../cloud_security_posture/links'; +import { IconActionHistory } from './icons/action_history'; import { IconBlocklist } from './icons/blocklist'; import { IconEndpoints } from './icons/endpoints'; import { IconEndpointPolicies } from './icons/endpoint_policies'; @@ -69,6 +72,7 @@ const categories = [ SecurityPageName.eventFilters, SecurityPageName.hostIsolationExceptions, SecurityPageName.blocklist, + SecurityPageName.actionHistory, ], }, ...cloudSecurityPostureCategories, @@ -202,6 +206,17 @@ export const links: LinkItem = { skipUrlState: true, hideTimeline: true, }, + { + id: SecurityPageName.actionHistory, + title: ACTION_HISTORY, + description: i18n.translate('xpack.securitySolution.appLinks.actionHistoryDescription', { + defaultMessage: 'View the history of response actions performed on hosts.', + }), + landingIcon: IconActionHistory, + path: ACTION_HISTORY_PATH, + skipUrlState: true, + hideTimeline: true, + }, cloudSecurityPostureLinks, ], }; diff --git a/x-pack/plugins/security_solution/public/management/pages/index.tsx b/x-pack/plugins/security_solution/public/management/pages/index.tsx index b78ad462ae8a17..2a54557b0095b4 100644 --- a/x-pack/plugins/security_solution/public/management/pages/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/index.tsx @@ -17,7 +17,7 @@ import { MANAGEMENT_ROUTING_POLICIES_PATH, MANAGEMENT_ROUTING_TRUSTED_APPS_PATH, MANAGEMENT_ROUTING_BLOCKLIST_PATH, - MANAGEMENT_ROUTING_RESPONSE_ACTIONS_PATH, + MANAGEMENT_ROUTING_ACTION_HISTORY_PATH, } from '../common/constants'; import { NotFoundPage } from '../../app/404'; import { EndpointsContainer } from './endpoint_hosts'; @@ -69,9 +69,9 @@ const HostIsolationExceptionsTelemetry = () => ( ); const ResponseActionsTelemetry = () => ( - + - + ); @@ -103,7 +103,7 @@ export const ManagementContainer = memo(() => { component={HostIsolationExceptionsTelemetry} /> - + diff --git a/x-pack/plugins/security_solution/public/management/pages/response_actions/index.tsx b/x-pack/plugins/security_solution/public/management/pages/response_actions/index.tsx index f759830f555fe9..0d3f029cc34cec 100644 --- a/x-pack/plugins/security_solution/public/management/pages/response_actions/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/response_actions/index.tsx @@ -7,7 +7,7 @@ import { Switch } from 'react-router-dom'; import { Route } from '@kbn/kibana-react-plugin/public'; import React, { memo } from 'react'; -import { MANAGEMENT_ROUTING_RESPONSE_ACTIONS_PATH } from '../../common/constants'; +import { MANAGEMENT_ROUTING_ACTION_HISTORY_PATH } from '../../common/constants'; import { NotFoundPage } from '../../../app/404'; import { ResponseActionsListPage } from './view/response_actions_list_page'; @@ -15,7 +15,7 @@ export const ResponseActionsContainer = memo(() => { return ( diff --git a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx index 044632a3c39848..23b3da831ddac8 100644 --- a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx @@ -6,13 +6,18 @@ */ import React from 'react'; +import { ACTION_HISTORY } from '../../../../app/translations'; import { AdministrationListPage } from '../../../components/administration_list_page'; import { ResponseActionsLog } from '../../../components/endpoint_response_actions_list/response_actions_log'; import { UX_MESSAGES } from '../../../components/endpoint_response_actions_list/translations'; export const ResponseActionsListPage = () => { return ( - + ); diff --git a/x-pack/plugins/security_solution/public/management/types.ts b/x-pack/plugins/security_solution/public/management/types.ts index 2658bd7a58b224..96c1983c8f254e 100644 --- a/x-pack/plugins/security_solution/public/management/types.ts +++ b/x-pack/plugins/security_solution/public/management/types.ts @@ -31,7 +31,7 @@ export enum AdministrationSubTab { eventFilters = 'event_filters', hostIsolationExceptions = 'host_isolation_exceptions', blocklist = 'blocklist', - responseActions = 'response_actions', + actionHistory = 'action_history', } /** diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 7dc55e04a8e3e3..3e1a916085b401 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -28429,7 +28429,6 @@ "xpack.securitySolution.navigation.network": "Réseau", "xpack.securitySolution.navigation.newRuleTitle": "Créer une nouvelle règle", "xpack.securitySolution.navigation.overview": "Aperçu", - "xpack.securitySolution.navigation.responseActions": "Actions de réponse", "xpack.securitySolution.navigation.rules": "Règles", "xpack.securitySolution.navigation.threatIntelligence": "Threat Intelligence", "xpack.securitySolution.navigation.timelines": "Chronologies", @@ -28730,7 +28729,6 @@ "xpack.securitySolution.responseActionsList.list.screenReader.expand": "Développer les lignes", "xpack.securitySolution.responseActionsList.list.status": "Statut", "xpack.securitySolution.responseActionsList.list.time": "Heure", - "xpack.securitySolution.responseActionsList.list.title": "Actions de réponse", "xpack.securitySolution.responseActionsList.list.user": "Utilisateur", "xpack.securitySolution.riskScore.errorSearchDescription": "Une erreur s'est produite sur la recherche du score de risque", "xpack.securitySolution.riskScore.failSearchDescription": "Impossible de lancer une recherche sur le score de risque", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 63d3a23441a0d2..6c875ca0c23330 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -28406,7 +28406,6 @@ "xpack.securitySolution.navigation.network": "ネットワーク", "xpack.securitySolution.navigation.newRuleTitle": "新規ルールを作成", "xpack.securitySolution.navigation.overview": "概要", - "xpack.securitySolution.navigation.responseActions": "対応アクション", "xpack.securitySolution.navigation.rules": "ルール", "xpack.securitySolution.navigation.threatIntelligence": "脅威インテリジェンス", "xpack.securitySolution.navigation.timelines": "タイムライン", @@ -28707,7 +28706,6 @@ "xpack.securitySolution.responseActionsList.list.screenReader.expand": "行を展開", "xpack.securitySolution.responseActionsList.list.status": "ステータス", "xpack.securitySolution.responseActionsList.list.time": "時間", - "xpack.securitySolution.responseActionsList.list.title": "対応アクション", "xpack.securitySolution.responseActionsList.list.user": "ユーザー", "xpack.securitySolution.riskScore.errorSearchDescription": "リスクスコア検索でエラーが発生しました", "xpack.securitySolution.riskScore.failSearchDescription": "リスクスコアで検索を実行できませんでした", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 68ba5c3825b790..05d1f7e1f51e85 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -28437,7 +28437,6 @@ "xpack.securitySolution.navigation.network": "网络", "xpack.securitySolution.navigation.newRuleTitle": "创建新规则", "xpack.securitySolution.navigation.overview": "概览", - "xpack.securitySolution.navigation.responseActions": "响应操作", "xpack.securitySolution.navigation.rules": "规则", "xpack.securitySolution.navigation.threatIntelligence": "威胁情报", "xpack.securitySolution.navigation.timelines": "时间线", @@ -28738,7 +28737,6 @@ "xpack.securitySolution.responseActionsList.list.screenReader.expand": "展开行", "xpack.securitySolution.responseActionsList.list.status": "状态", "xpack.securitySolution.responseActionsList.list.time": "时间", - "xpack.securitySolution.responseActionsList.list.title": "响应操作", "xpack.securitySolution.responseActionsList.list.user": "用户", "xpack.securitySolution.riskScore.errorSearchDescription": "搜索风险分数时发生错误", "xpack.securitySolution.riskScore.failSearchDescription": "无法对风险分数执行搜索", From a26cc71578ae1aa0e2decd4f24236baae1d5253c Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 9 Sep 2022 12:23:44 -0500 Subject: [PATCH 026/144] expand skip because of cross-suite dependencies (#140437) --- .../test/observability_functional/apps/observability/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index b3acbf5f51a8a9..60a4c2a571a1ca 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -8,7 +8,8 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - describe('ObservabilityApp', function () { + // FAILING: https://github.com/elastic/kibana/issues/140437 + describe.skip('ObservabilityApp', function () { loadTestFile(require.resolve('./pages/alerts')); loadTestFile(require.resolve('./pages/cases/case_details')); loadTestFile(require.resolve('./pages/alerts/add_to_case')); From 95c3893e2805afcb2630ece3ee4d3ec44b7e105f Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Fri, 9 Sep 2022 10:25:36 -0700 Subject: [PATCH 027/144] [Search] Re-enable test on example search app (#139961) * [Search] Unskip ex-flaky example app test * comment out flaky test code * use es.transport.request to downsample the test index * uncomment blocked test code * remove browser refresh in beforeEach * fix ts --- .../search_examples/public/search/app.tsx | 6 +- test/examples/search/warnings.ts | 62 +++++++++++-------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/examples/search_examples/public/search/app.tsx b/examples/search_examples/public/search/app.tsx index 94cf19436c3f55..01ebd4433af10b 100644 --- a/examples/search_examples/public/search/app.tsx +++ b/examples/search_examples/public/search/app.tsx @@ -107,9 +107,9 @@ export const SearchExamplesApp = ({ const [selectedBucketField, setSelectedBucketField] = useState< DataViewField | null | undefined >(); - const [request, setRequest] = useState>({}); const [isLoading, setIsLoading] = useState(false); const [currentAbortController, setAbortController] = useState(); + const [request, setRequest] = useState>({}); const [rawResponse, setRawResponse] = useState>({}); const [warningContents, setWarningContents] = useState([]); const [selectedTab, setSelectedTab] = useState(0); @@ -202,6 +202,8 @@ export const SearchExamplesApp = ({ // Submit the search request using the `data.search` service. setRequest(req.params.body); + setRawResponse({}); + setWarningContents([]); setIsLoading(true); data.search @@ -301,6 +303,8 @@ export const SearchExamplesApp = ({ searchSource.setField('aggs', ac); } setRequest(searchSource.getSearchRequestBody()); + setRawResponse({}); + setWarningContents([]); const abortController = new AbortController(); const inspector: Required = { diff --git a/test/examples/search/warnings.ts b/test/examples/search/warnings.ts index 05179aa926f86c..fc1949549d66e8 100644 --- a/test/examples/search/warnings.ts +++ b/test/examples/search/warnings.ts @@ -6,15 +6,19 @@ * Side Public License, v 1. */ +import type { estypes } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { asyncForEach } from '@kbn/std'; -import { FtrProviderContext } from '../../functional/ftr_provider_context'; +import assert from 'assert'; +import type { FtrProviderContext } from '../../functional/ftr_provider_context'; +import type { WebElementWrapper } from '../../functional/services/lib/web_element_wrapper'; // eslint-disable-next-line import/no-default-export export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'timePicker']); const testSubjects = getService('testSubjects'); const find = getService('find'); + const retry = getService('retry'); const es = getService('es'); const log = getService('log'); const indexPatterns = getService('indexPatterns'); @@ -22,8 +26,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); - // Failing: See https://github.com/elastic/kibana/issues/139879 - describe.skip('handling warnings with search source fetch', function () { + describe('handling warnings with search source fetch', function () { const dataViewTitle = 'sample-01,sample-01-rollup'; const fromTime = 'Jun 17, 2022 @ 00:00:00.000'; const toTime = 'Jun 23, 2022 @ 00:00:00.000'; @@ -51,10 +54,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await es.indices.addBlock({ index: testIndex, block: 'write' }); try { log.info(`rolling up ${testIndex} index...`); - await es.rollup.rollup({ - index: testIndex, - rollup_index: testRollupIndex, - config: { fixed_interval: '1h' }, + // es client currently does not have method for downsample + await es.transport.request({ + method: 'POST', + path: '/sample-01/_downsample/sample-01-rollup', + body: { fixed_interval: '1h' }, }); } catch (err) { log.info(`ignoring resource_already_exists_exception...`); @@ -76,6 +80,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { defaultIndex: '0ae0bc7a-e4ca-405c-ab67-f2b5913f2a51', 'timepicker:timeDefaults': '{ "from": "now-1y", "to": "now" }', }); + + await PageObjects.common.navigateToApp('searchExamples'); + }); + + beforeEach(async () => { + await comboBox.setCustom('dataViewSelector', dataViewTitle); + await comboBox.set('searchMetricField', testRollupField); + await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); }); after(async () => { @@ -84,23 +96,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await kibanaServer.uiSettings.replace({}); }); - beforeEach(async () => { - // reload the page to clear toasts from previous test - - await PageObjects.common.navigateToApp('searchExamples'); - - await comboBox.setCustom('dataViewSelector', dataViewTitle); - await comboBox.set('searchMetricField', testRollupField); - await PageObjects.timePicker.setAbsoluteRange(fromTime, toTime); + afterEach(async () => { + await PageObjects.common.clearAllToasts(); }); it('shows shard failure warning notifications by default', async () => { await testSubjects.click('searchSourceWithOther'); + // wait for response - toasts appear before the response is rendered + let response: estypes.SearchResponse | undefined; + await retry.try(async () => { + response = await getTestJson('responseTab', 'responseCodeBlock'); + expect(response).not.to.eql({}); + }); + // toasts const toasts = await find.allByCssSelector(toastsSelector); - expect(toasts.length).to.be(3); - const expects = ['2 of 4 shards failed', '2 of 4 shards failed', 'Query result']; // BUG: there are 2 shards failed toast notifications + expect(toasts.length).to.be(2); + const expects = ['2 of 4 shards failed', 'Query result']; await asyncForEach(toasts, async (t, index) => { expect(await t.getVisibleText()).to.eql(expects[index]); }); @@ -119,12 +132,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const responseBlock = await testSubjects.find('shardsFailedModalResponseBlock'); expect(await responseBlock.getVisibleText()).to.contain(shardFailureReason); - // close things await testSubjects.click('closeShardFailureModal'); - await PageObjects.common.clearAllToasts(); // response tab - const response = await getTestJson('responseTab', 'responseCodeBlock'); + assert(response && response._shards.failures); expect(response._shards.total).to.be(4); expect(response._shards.successful).to.be(2); expect(response._shards.skipped).to.be(0); @@ -142,9 +153,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('able to handle shard failure warnings and prevent default notifications', async () => { await testSubjects.click('searchSourceWithoutOther'); - // toasts - const toasts = await find.allByCssSelector(toastsSelector); - expect(toasts.length).to.be(2); + // wait for toasts - toasts appear after the response is rendered + let toasts: WebElementWrapper[] = []; + await retry.try(async () => { + toasts = await find.allByCssSelector(toastsSelector); + expect(toasts.length).to.be(2); + }); const expects = ['2 of 4 shards failed', 'Query result']; await asyncForEach(toasts, async (t, index) => { expect(await t.getVisibleText()).to.eql(expects[index]); @@ -164,9 +178,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const responseBlock = await testSubjects.find('shardsFailedModalResponseBlock'); expect(await responseBlock.getVisibleText()).to.contain(shardFailureReason); - // close things await testSubjects.click('closeShardFailureModal'); - await PageObjects.common.clearAllToasts(); // response tab const response = await getTestJson('responseTab', 'responseCodeBlock'); From 1530f8e1d303e1bc6874cae74f07f403c8c1d9ac Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 9 Sep 2022 12:44:00 -0500 Subject: [PATCH 028/144] [ftr] support redirecting server logs to a file (#140334) --- packages/kbn-dev-proc-runner/src/proc.ts | 32 ++- .../kbn-dev-proc-runner/src/proc_runner.ts | 6 +- packages/kbn-es/src/cluster.js | 48 +++- packages/kbn-test/src/es/test_es_cluster.ts | 3 + .../run_tests/__snapshots__/args.test.js.snap | 14 ++ .../run_tests/__snapshots__/cli.test.js.snap | 74 ------ .../functional_tests/cli/run_tests/args.js | 22 +- .../src/functional_tests/cli/run_tests/cli.js | 3 +- .../cli/run_tests/cli.test.js | 232 ------------------ .../__snapshots__/args.test.js.snap | 11 + .../__snapshots__/cli.test.js.snap | 50 ---- .../cli/start_servers/args.js | 23 +- .../functional_tests/cli/start_servers/cli.js | 3 +- .../cli/start_servers/cli.test.js | 192 --------------- .../functional_tests/lib/run_elasticsearch.ts | 54 ++-- .../functional_tests/lib/run_kibana_server.ts | 15 +- .../kbn-test/src/functional_tests/tasks.ts | 11 + 17 files changed, 204 insertions(+), 589 deletions(-) delete mode 100644 packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap delete mode 100644 packages/kbn-test/src/functional_tests/cli/run_tests/cli.test.js delete mode 100644 packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/cli.test.js.snap delete mode 100644 packages/kbn-test/src/functional_tests/cli/start_servers/cli.test.js diff --git a/packages/kbn-dev-proc-runner/src/proc.ts b/packages/kbn-dev-proc-runner/src/proc.ts index ffe7cb64641239..d30a893ae4c759 100644 --- a/packages/kbn-dev-proc-runner/src/proc.ts +++ b/packages/kbn-dev-proc-runner/src/proc.ts @@ -6,8 +6,10 @@ * Side Public License, v 1. */ -import { statSync } from 'fs'; +import Fs from 'fs'; +import Path from 'path'; import { promisify } from 'util'; +import stripAnsi from 'strip-ansi'; import execa from 'execa'; import * as Rx from 'rxjs'; @@ -29,6 +31,7 @@ export interface ProcOptions { cwd: string; env?: Record; stdin?: string; + writeLogsToPath?: string; } async function withTimeout( @@ -44,13 +47,21 @@ export type Proc = ReturnType; export function startProc(name: string, options: ProcOptions, log: ToolingLog) { const { cmd, args, cwd, env, stdin } = options; - log.info('[%s] > %s', name, cmd === process.execPath ? 'node' : cmd, args.join(' ')); + let stdioTarget: undefined | NodeJS.WritableStream; + if (!options.writeLogsToPath) { + log.info('starting [%s] > %s', name, cmd === process.execPath ? 'node' : cmd, args.join(' ')); + } else { + stdioTarget = Fs.createWriteStream(options.writeLogsToPath, 'utf8'); + const exec = cmd === process.execPath ? 'node' : cmd; + const relOut = Path.relative(process.cwd(), options.writeLogsToPath); + log.info(`starting [${name}] and writing output to ${relOut} > ${exec} ${args.join(' ')}`); + } // spawn fails with ENOENT when either the // cmd or cwd don't exist, so we check for the cwd // ahead of time so that the error is less ambiguous try { - if (!statSync(cwd).isDirectory()) { + if (!Fs.statSync(cwd).isDirectory()) { throw new Error(`cwd "${cwd}" exists but is not a directory`); } } catch (err) { @@ -104,7 +115,20 @@ export function startProc(name: string, options: ProcOptions, log: ToolingLog) { observeLines(childProcess.stdout!), // TypeScript note: As long as the proc stdio[1] is 'pipe', then stdout will not be null observeLines(childProcess.stderr!) // TypeScript note: As long as the proc stdio[1] is 'pipe', then stderr will not be null ).pipe( - tap((line) => log.write(` ${chalk.gray('proc')} [${chalk.gray(name)}] ${line}`)), + tap({ + next(line) { + if (stdioTarget) { + stdioTarget.write(stripAnsi(line) + '\n'); + } else { + log.write(` ${chalk.gray('proc')} [${chalk.gray(name)}] ${line}`); + } + }, + complete() { + if (stdioTarget) { + stdioTarget.end(); + } + }, + }), share() ); diff --git a/packages/kbn-dev-proc-runner/src/proc_runner.ts b/packages/kbn-dev-proc-runner/src/proc_runner.ts index 56a6ee48c31506..1226cbeb3eef18 100644 --- a/packages/kbn-dev-proc-runner/src/proc_runner.ts +++ b/packages/kbn-dev-proc-runner/src/proc_runner.ts @@ -36,12 +36,12 @@ export class ProcRunner { private procs: Proc[] = []; private signalUnsubscribe: () => void; - constructor(private log: ToolingLog) { + constructor(private readonly log: ToolingLog) { this.log = log.withType('ProcRunner'); this.signalUnsubscribe = exitHook(() => { this.teardown().catch((error) => { - log.error(`ProcRunner teardown error: ${error.stack}`); + this.log.error(`ProcRunner teardown error: ${error.stack}`); }); }); } @@ -58,6 +58,7 @@ export class ProcRunner { waitTimeout = 15 * MINUTE, env = process.env, onEarlyExit, + writeLogsToPath, } = options; const cmd = options.cmd === 'node' ? process.execPath : options.cmd; @@ -79,6 +80,7 @@ export class ProcRunner { cwd, env, stdin, + writeLogsToPath, }); if (onEarlyExit) { diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index 5c410523d70ca6..a027db201b002c 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -6,10 +6,12 @@ * Side Public License, v 1. */ +const fs = require('fs'); const fsp = require('fs/promises'); const execa = require('execa'); const chalk = require('chalk'); const path = require('path'); +const Rx = require('rxjs'); const { Client } = require('@elastic/elasticsearch'); const { downloadSnapshot, installSnapshot, installSource, installArchive } = require('./install'); const { ES_BIN, ES_PLUGIN_BIN, ES_KEYSTORE_BIN } = require('./paths'); @@ -315,6 +317,7 @@ exports.Cluster = class Cluster { startTime, skipReadyCheck, readyTimeout, + writeLogsToPath, ...options } = opts; @@ -322,7 +325,19 @@ exports.Cluster = class Cluster { throw new Error('ES has already been started'); } - this._log.info(chalk.bold('Starting')); + /** @type {NodeJS.WritableStream | undefined} */ + let stdioTarget; + + if (writeLogsToPath) { + stdioTarget = fs.createWriteStream(writeLogsToPath, 'utf8'); + this._log.info( + chalk.bold('Starting'), + `and writing logs to ${path.relative(process.cwd(), writeLogsToPath)}` + ); + } else { + this._log.info(chalk.bold('Starting')); + } + this._log.indent(4); const esArgs = new Map([ @@ -428,7 +443,8 @@ exports.Cluster = class Cluster { let reportSent = false; // parse and forward es stdout to the log this._process.stdout.on('data', (data) => { - const lines = parseEsLog(data.toString()); + const chunk = data.toString(); + const lines = parseEsLog(chunk); lines.forEach((line) => { if (!reportSent && line.message.includes('publish_address')) { reportSent = true; @@ -436,12 +452,36 @@ exports.Cluster = class Cluster { success: true, }); } - this._log.info(line.formattedMessage); + + if (stdioTarget) { + stdioTarget.write(chunk); + } else { + this._log.info(line.formattedMessage); + } }); }); // forward es stderr to the log - this._process.stderr.on('data', (data) => this._log.error(chalk.red(data.toString()))); + this._process.stderr.on('data', (data) => { + const chunk = data.toString(); + if (stdioTarget) { + stdioTarget.write(chunk); + } else { + this._log.error(chalk.red()); + } + }); + + // close the stdio target if we have one defined + if (stdioTarget) { + Rx.combineLatest([ + Rx.fromEvent(this._process.stderr, 'end'), + Rx.fromEvent(this._process.stdout, 'end'), + ]) + .pipe(Rx.first()) + .subscribe(() => { + stdioTarget.end(); + }); + } // observe the exit code of the process and reflect in _outcome promies const exitCode = new Promise((resolve) => this._process.once('exit', resolve)); diff --git a/packages/kbn-test/src/es/test_es_cluster.ts b/packages/kbn-test/src/es/test_es_cluster.ts index 8c650ec9b60518..70fa5f2e8d3759 100644 --- a/packages/kbn-test/src/es/test_es_cluster.ts +++ b/packages/kbn-test/src/es/test_es_cluster.ts @@ -95,6 +95,7 @@ export interface CreateTestEsClusterOptions { */ license?: 'basic' | 'gold' | 'trial'; // | 'oss' log: ToolingLog; + writeLogsToPath?: string; /** * Node-specific configuration if you wish to run a multi-node * cluster. One node will be added for each item in the array. @@ -168,6 +169,7 @@ export function createTestEsCluster< password = 'changeme', license = 'basic', log, + writeLogsToPath, basePath = Path.resolve(REPO_ROOT, '.es'), esFrom = esTestConfig.getBuildFrom(), dataArchive, @@ -272,6 +274,7 @@ export function createTestEsCluster< skipNativeRealmSetup: this.nodes.length > 1 && i < this.nodes.length - 1, skipReadyCheck: this.nodes.length > 1 && i < this.nodes.length - 1, onEarlyExit, + writeLogsToPath, }); }); } diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap b/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap index cff0b46afcad17..ff8961e263f170 100644 --- a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap +++ b/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/args.test.js.snap @@ -23,6 +23,7 @@ Options: --include-tag Tags that suites must include to be run, can be included multiple times. --exclude-tag Tags that suites must NOT include to be run, can be included multiple times. --assert-none-excluded Exit with 1/0 based on if any test is excluded with the current set of tags. + --logToFile Write the log output from Kibana/Elasticsearch to files instead of to stdout --verbose Log everything. --debug Run in debug mode. --quiet Only log errors. @@ -40,6 +41,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -62,6 +64,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -85,6 +88,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -107,6 +111,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -133,6 +138,7 @@ Object { "extraKbnOpts": Object { "server.foo": "bar", }, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -154,6 +160,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "quiet": true, "suiteFiles": Object { "exclude": Array [], @@ -176,6 +183,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "silent": true, "suiteFiles": Object { "exclude": Array [], @@ -198,6 +206,7 @@ Object { "esFrom": "source", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -219,6 +228,7 @@ Object { "esFrom": "source", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -241,6 +251,7 @@ Object { "esVersion": "999.999.999", "extraKbnOpts": undefined, "installDir": "foo", + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -263,6 +274,7 @@ Object { "esVersion": "999.999.999", "extraKbnOpts": undefined, "grep": "management", + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -284,6 +296,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], @@ -306,6 +319,7 @@ Object { "esFrom": "snapshot", "esVersion": "999.999.999", "extraKbnOpts": undefined, + "logsDir": undefined, "suiteFiles": Object { "exclude": Array [], "include": Array [], diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap b/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap deleted file mode 100644 index 6b81c2e499cf4c..00000000000000 --- a/packages/kbn-test/src/functional_tests/cli/run_tests/__snapshots__/cli.test.js.snap +++ /dev/null @@ -1,74 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`run tests CLI options accepts help option even if invalid options passed 1`] = ` -"Run Functional Tests - -Usage: - node scripts/functional_tests --help - node scripts/functional_tests [--config [--config ...]] - node scripts/functional_tests [options] [-- --] - -Options: - --help Display this menu and exit. - --config Pass in a config. Can pass in multiple configs. - --esFrom Build Elasticsearch from source or run from snapshot. Default: $TEST_ES_FROM or snapshot - --kibana-install-dir Run Kibana from existing install directory instead of from source. - --bail Stop the test run at the first failure. - --grep Pattern to select which tests to run. - --updateBaselines Replace baseline screenshots with whatever is generated from the test. - --updateSnapshots Replace inline and file snapshots with whatever is generated from the test. - --u Replace both baseline screenshots and snapshots - --include Files that must included to be run, can be included multiple times. - --exclude Files that must NOT be included to be run, can be included multiple times. - --include-tag Tags that suites must include to be run, can be included multiple times. - --exclude-tag Tags that suites must NOT include to be run, can be included multiple times. - --assert-none-excluded Exit with 1/0 based on if any test is excluded with the current set of tags. - --verbose Log everything. - --debug Run in debug mode. - --quiet Only log errors. - --silent Log nothing. - --dry-run Report tests without executing them. -" -`; - -exports[`run tests CLI options rejects boolean config value 1`] = ` -" -functional_tests: invalid argument [true] to option [config] - ...stack trace... -" -`; - -exports[`run tests CLI options rejects boolean value for kibana-install-dir 1`] = ` -" -functional_tests: invalid argument [true] to option [kibana-install-dir] - ...stack trace... -" -`; - -exports[`run tests CLI options rejects empty config value if no default passed 1`] = ` -" -functional_tests: config is required - ...stack trace... -" -`; - -exports[`run tests CLI options rejects invalid options even if valid options exist 1`] = ` -" -functional_tests: invalid option [aintnothang] - ...stack trace... -" -`; - -exports[`run tests CLI options rejects non-boolean value for bail 1`] = ` -" -functional_tests: invalid argument [peanut] to option [bail] - ...stack trace... -" -`; - -exports[`run tests CLI options rejects non-enum value for esFrom 1`] = ` -" -functional_tests: invalid argument [butter] to option [esFrom] - ...stack trace... -" -`; diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/args.js b/packages/kbn-test/src/functional_tests/cli/run_tests/args.js index d94adcfe615a5d..8b1bf471f4e98f 100644 --- a/packages/kbn-test/src/functional_tests/cli/run_tests/args.js +++ b/packages/kbn-test/src/functional_tests/cli/run_tests/args.js @@ -6,9 +6,11 @@ * Side Public License, v 1. */ -import { resolve } from 'path'; +import Path from 'path'; +import { v4 as uuid } from 'uuid'; import dedent from 'dedent'; +import { REPO_ROOT } from '@kbn/utils'; import { ToolingLog, pickLevelFromFlags } from '@kbn/tooling-log'; import { EsVersion } from '../../../functional_test_runner'; @@ -61,6 +63,9 @@ const options = { 'assert-none-excluded': { desc: 'Exit with 1/0 based on if any test is excluded with the current set of tags.', }, + logToFile: { + desc: 'Write the log output from Kibana/Elasticsearch to files instead of to stdout', + }, verbose: { desc: 'Log everything.' }, debug: { desc: 'Run in debug mode.' }, quiet: { desc: 'Only log errors.' }, @@ -142,19 +147,24 @@ export function processOptions(userOptions, defaultConfigPaths) { delete userOptions['dry-run']; } + const log = new ToolingLog({ + level: pickLevelFromFlags(userOptions), + writeTo: process.stdout, + }); function createLogger() { - return new ToolingLog({ - level: pickLevelFromFlags(userOptions), - writeTo: process.stdout, - }); + return log; } + const logToFile = !!userOptions.logToFile; + const logsDir = logToFile ? Path.resolve(REPO_ROOT, 'data/ftr_servers_logs', uuid()) : undefined; + return { ...userOptions, - configs: configs.map((c) => resolve(c)), + configs: configs.map((c) => Path.resolve(c)), createLogger, extraKbnOpts: userOptions._, esVersion: EsVersion.getDefault(), + logsDir, }; } diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js b/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js index e920e43f375b4b..3958c1503cd30b 100644 --- a/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js +++ b/packages/kbn-test/src/functional_tests/cli/run_tests/cli.js @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { runTests } from '../../tasks'; +import { runTests, initLogsDir } from '../../tasks'; import { runCli } from '../../lib'; import { processOptions, displayHelp } from './args'; @@ -21,6 +21,7 @@ import { processOptions, displayHelp } from './args'; export async function runTestsCli(defaultConfigPaths) { await runCli(displayHelp, async (userOptions) => { const options = processOptions(userOptions, defaultConfigPaths); + initLogsDir(options); await runTests(options); }); } diff --git a/packages/kbn-test/src/functional_tests/cli/run_tests/cli.test.js b/packages/kbn-test/src/functional_tests/cli/run_tests/cli.test.js deleted file mode 100644 index 1b679f285d1332..00000000000000 --- a/packages/kbn-test/src/functional_tests/cli/run_tests/cli.test.js +++ /dev/null @@ -1,232 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Writable } from 'stream'; - -import { runTestsCli } from './cli'; -import { checkMockConsoleLogSnapshot } from '../../test_helpers'; - -// Note: Stub the runTests function to keep testing only around the cli -// method and arguments. -jest.mock('../../tasks', () => ({ - runTests: jest.fn(), -})); - -describe('run tests CLI', () => { - describe('options', () => { - const originalObjects = { process, console }; - const exitMock = jest.fn(); - const logMock = jest.fn(); // mock logging so we don't send output to the test results - const argvMock = ['foo', 'foo']; - - const processMock = { - exit: exitMock, - argv: argvMock, - stdout: new Writable(), - cwd: jest.fn(), - env: { - ...originalObjects.process.env, - TEST_ES_FROM: 'snapshot', - }, - }; - - beforeAll(() => { - global.process = processMock; - global.console = { log: logMock }; - }); - - afterAll(() => { - global.process = originalObjects.process; - global.console = originalObjects.console; - }); - - beforeEach(() => { - global.process.argv = [...argvMock]; - global.process.env = { - ...originalObjects.process.env, - TEST_ES_FROM: 'snapshot', - }; - jest.resetAllMocks(); - }); - - it('rejects boolean config value', async () => { - global.process.argv.push('--config'); - - await runTestsCli(); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('rejects empty config value if no default passed', async () => { - global.process.argv.push('--config', ''); - - await runTestsCli(); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts empty config value if default passed', async () => { - global.process.argv.push('--config', ''); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('rejects non-boolean value for bail', async () => { - global.process.argv.push('--bail', 'peanut'); - - await runTestsCli(['foo']); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts string value for kibana-install-dir', async () => { - global.process.argv.push('--kibana-install-dir', 'foo'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('rejects boolean value for kibana-install-dir', async () => { - global.process.argv.push('--kibana-install-dir'); - - await runTestsCli(['foo']); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts boolean value for updateBaselines', async () => { - global.process.argv.push('--updateBaselines'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalledWith(); - }); - - it('accepts boolean value for updateSnapshots', async () => { - global.process.argv.push('--updateSnapshots'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalledWith(); - }); - - it('accepts boolean value for -u', async () => { - global.process.argv.push('-u'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalledWith(); - }); - - it('accepts source value for esFrom', async () => { - global.process.argv.push('--esFrom', 'source'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('rejects non-enum value for esFrom', async () => { - global.process.argv.push('--esFrom', 'butter'); - - await runTestsCli(['foo']); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts value for grep', async () => { - global.process.argv.push('--grep', 'management'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts debug option', async () => { - global.process.argv.push('--debug'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts silent option', async () => { - global.process.argv.push('--silent'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts quiet option', async () => { - global.process.argv.push('--quiet'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts verbose option', async () => { - global.process.argv.push('--verbose'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts network throttle option', async () => { - global.process.argv.push('--throttle'); - - await runTestsCli(['foo']); - - expect(exitMock).toHaveBeenCalledWith(1); - }); - - it('accepts headless option', async () => { - global.process.argv.push('--headless'); - - await runTestsCli(['foo']); - - expect(exitMock).toHaveBeenCalledWith(1); - }); - - it('accepts extra server options', async () => { - global.process.argv.push('--', '--server.foo=bar'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts help option even if invalid options passed', async () => { - global.process.argv.push('--debug', '--aintnothang', '--help'); - - await runTestsCli(['foo']); - - expect(exitMock).not.toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('rejects invalid options even if valid options exist', async () => { - global.process.argv.push('--debug', '--aintnothang', '--bail'); - - await runTestsCli(['foo']); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - }); -}); diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/args.test.js.snap b/packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/args.test.js.snap index cd3174d13c3e69..1f572578119f77 100644 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/args.test.js.snap +++ b/packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/args.test.js.snap @@ -13,6 +13,7 @@ Options: --config Pass in a config --esFrom Build Elasticsearch from source, snapshot or path to existing install dir. Default: $TEST_ES_FROM or snapshot --kibana-install-dir Run Kibana from existing install directory instead of from source. + --logToFile Write the log output from Kibana/Elasticsearch to files instead of to stdout --verbose Log everything. --debug Run in debug mode. --quiet Only log errors. @@ -26,6 +27,7 @@ Object { "debug": true, "esFrom": "snapshot", "extraKbnOpts": undefined, + "logsDir": undefined, "useDefaultConfig": true, } `; @@ -36,6 +38,7 @@ Object { "createLogger": [Function], "esFrom": "snapshot", "extraKbnOpts": undefined, + "logsDir": undefined, "useDefaultConfig": true, } `; @@ -51,6 +54,7 @@ Object { "extraKbnOpts": Object { "server.foo": "bar", }, + "logsDir": undefined, "useDefaultConfig": true, } `; @@ -61,6 +65,7 @@ Object { "createLogger": [Function], "esFrom": "snapshot", "extraKbnOpts": undefined, + "logsDir": undefined, "quiet": true, "useDefaultConfig": true, } @@ -72,6 +77,7 @@ Object { "createLogger": [Function], "esFrom": "snapshot", "extraKbnOpts": undefined, + "logsDir": undefined, "silent": true, "useDefaultConfig": true, } @@ -83,6 +89,7 @@ Object { "createLogger": [Function], "esFrom": "source", "extraKbnOpts": undefined, + "logsDir": undefined, "useDefaultConfig": true, } `; @@ -93,6 +100,7 @@ Object { "createLogger": [Function], "esFrom": "source", "extraKbnOpts": undefined, + "logsDir": undefined, "useDefaultConfig": true, } `; @@ -104,6 +112,7 @@ Object { "esFrom": "snapshot", "extraKbnOpts": undefined, "installDir": "foo", + "logsDir": undefined, "useDefaultConfig": true, } `; @@ -114,6 +123,7 @@ Object { "createLogger": [Function], "esFrom": "snapshot", "extraKbnOpts": undefined, + "logsDir": undefined, "useDefaultConfig": true, "verbose": true, } @@ -125,6 +135,7 @@ Object { "createLogger": [Function], "esFrom": "snapshot", "extraKbnOpts": undefined, + "logsDir": undefined, "useDefaultConfig": true, } `; diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/cli.test.js.snap b/packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/cli.test.js.snap deleted file mode 100644 index ba085b08682169..00000000000000 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/__snapshots__/cli.test.js.snap +++ /dev/null @@ -1,50 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`start servers CLI options accepts boolean value for updateBaselines 1`] = ` -" -functional_tests_server: invalid option [updateBaselines] - ...stack trace... -" -`; - -exports[`start servers CLI options accepts boolean value for updateSnapshots 1`] = ` -" -functional_tests_server: invalid option [updateSnapshots] - ...stack trace... -" -`; - -exports[`start servers CLI options rejects bail 1`] = ` -" -functional_tests_server: invalid option [bail] - ...stack trace... -" -`; - -exports[`start servers CLI options rejects boolean config value 1`] = ` -" -functional_tests_server: invalid argument [true] to option [config] - ...stack trace... -" -`; - -exports[`start servers CLI options rejects boolean value for kibana-install-dir 1`] = ` -" -functional_tests_server: invalid argument [true] to option [kibana-install-dir] - ...stack trace... -" -`; - -exports[`start servers CLI options rejects empty config value if no default passed 1`] = ` -" -functional_tests_server: config is required - ...stack trace... -" -`; - -exports[`start servers CLI options rejects invalid options even if valid options exist 1`] = ` -" -functional_tests_server: invalid option [grep] - ...stack trace... -" -`; diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/args.js b/packages/kbn-test/src/functional_tests/cli/start_servers/args.js index 527e3ce64613dc..e025bdc3393318 100644 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/args.js +++ b/packages/kbn-test/src/functional_tests/cli/start_servers/args.js @@ -6,9 +6,11 @@ * Side Public License, v 1. */ -import { resolve } from 'path'; +import Path from 'path'; +import { v4 as uuid } from 'uuid'; import dedent from 'dedent'; +import { REPO_ROOT } from '@kbn/utils'; import { ToolingLog, pickLevelFromFlags } from '@kbn/tooling-log'; const options = { @@ -26,6 +28,9 @@ const options = { arg: '', desc: 'Run Kibana from existing install directory instead of from source.', }, + logToFile: { + desc: 'Write the log output from Kibana/Elasticsearch to files instead of to stdout', + }, verbose: { desc: 'Log everything.' }, debug: { desc: 'Run in debug mode.' }, quiet: { desc: 'Only log errors.' }, @@ -80,16 +85,22 @@ export function processOptions(userOptions, defaultConfigPath) { delete userOptions['kibana-install-dir']; } + const log = new ToolingLog({ + level: pickLevelFromFlags(userOptions), + writeTo: process.stdout, + }); + function createLogger() { - return new ToolingLog({ - level: pickLevelFromFlags(userOptions), - writeTo: process.stdout, - }); + return log; } + const logToFile = !!userOptions.logToFile; + const logsDir = logToFile ? Path.resolve(REPO_ROOT, 'data/ftr_servers_logs', uuid()) : undefined; + return { ...userOptions, - config: resolve(config), + logsDir, + config: Path.resolve(config), useDefaultConfig, createLogger, extraKbnOpts: userOptions._, diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js b/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js index df7f8750b2ae31..d57d5c4761f6ea 100644 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js +++ b/packages/kbn-test/src/functional_tests/cli/start_servers/cli.js @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { startServers } from '../../tasks'; +import { startServers, initLogsDir } from '../../tasks'; import { runCli } from '../../lib'; import { processOptions, displayHelp } from './args'; @@ -18,6 +18,7 @@ import { processOptions, displayHelp } from './args'; export async function startServersCli(defaultConfigPath) { await runCli(displayHelp, async (userOptions) => { const options = processOptions(userOptions, defaultConfigPath); + initLogsDir(options); await startServers({ ...options, }); diff --git a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.test.js b/packages/kbn-test/src/functional_tests/cli/start_servers/cli.test.js deleted file mode 100644 index a88e4dbd011692..00000000000000 --- a/packages/kbn-test/src/functional_tests/cli/start_servers/cli.test.js +++ /dev/null @@ -1,192 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Writable } from 'stream'; - -import { startServersCli } from './cli'; -import { checkMockConsoleLogSnapshot } from '../../test_helpers'; - -// Note: Stub the startServers function to keep testing only around the cli -// method and arguments. -jest.mock('../../tasks', () => ({ - startServers: jest.fn(), -})); - -describe('start servers CLI', () => { - describe('options', () => { - const originalObjects = { process, console }; - const exitMock = jest.fn(); - const logMock = jest.fn(); // mock logging so we don't send output to the test results - const argvMock = ['foo', 'foo']; - - const processMock = { - exit: exitMock, - argv: argvMock, - stdout: new Writable(), - cwd: jest.fn(), - env: { - ...originalObjects.process.env, - TEST_ES_FROM: 'snapshot', - }, - }; - - beforeAll(() => { - global.process = processMock; - global.console = { log: logMock }; - }); - - afterAll(() => { - global.process = originalObjects.process; - global.console = originalObjects.console; - }); - - beforeEach(() => { - global.process.argv = [...argvMock]; - global.process.env = { - ...originalObjects.process.env, - TEST_ES_FROM: 'snapshot', - }; - jest.resetAllMocks(); - }); - - it('rejects boolean config value', async () => { - global.process.argv.push('--config'); - - await startServersCli(); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('rejects empty config value if no default passed', async () => { - global.process.argv.push('--config', ''); - - await startServersCli(); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts empty config value if default passed', async () => { - global.process.argv.push('--config', ''); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('rejects bail', async () => { - global.process.argv.push('--bail', true); - - await startServersCli('foo'); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts string value for kibana-install-dir', async () => { - global.process.argv.push('--kibana-install-dir', 'foo'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('rejects boolean value for kibana-install-dir', async () => { - global.process.argv.push('--kibana-install-dir'); - - await startServersCli('foo'); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts boolean value for updateBaselines', async () => { - global.process.argv.push('--updateBaselines'); - - await startServersCli('foo'); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts boolean value for updateSnapshots', async () => { - global.process.argv.push('--updateSnapshots'); - - await startServersCli('foo'); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - - it('accepts source value for esFrom', async () => { - global.process.argv.push('--esFrom', 'source'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts debug option', async () => { - global.process.argv.push('--debug'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts silent option', async () => { - global.process.argv.push('--silent'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts quiet option', async () => { - global.process.argv.push('--quiet'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts verbose option', async () => { - global.process.argv.push('--verbose'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts extra server options', async () => { - global.process.argv.push('--', '--server.foo=bar'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalled(); - }); - - it('accepts help option even if invalid options passed', async () => { - global.process.argv.push('--debug', '--grep', '--help'); - - await startServersCli('foo'); - - expect(exitMock).not.toHaveBeenCalledWith(1); - }); - - it('rejects invalid options even if valid options exist', async () => { - global.process.argv.push('--debug', '--grep', '--bail'); - - await startServersCli('foo'); - - expect(exitMock).toHaveBeenCalledWith(1); - checkMockConsoleLogSnapshot(logMock); - }); - }); -}); diff --git a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts index 5dcee56e765e0d..b367af4daf4921 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts +++ b/packages/kbn-test/src/functional_tests/lib/run_elasticsearch.ts @@ -18,6 +18,7 @@ interface RunElasticsearchOptions { esFrom?: string; config: Config; onEarlyExit?: (msg: string) => void; + logsDir?: string; } interface CcsConfig { @@ -62,26 +63,41 @@ function getEsConfig({ export async function runElasticsearch( options: RunElasticsearchOptions ): Promise<() => Promise> { - const { log } = options; + const { log, logsDir } = options; const config = getEsConfig(options); if (!config.ccsConfig) { - const node = await startEsNode(log, 'ftr', config); + const node = await startEsNode({ + log, + name: 'ftr', + logsDir, + config, + }); return async () => { await node.cleanup(); }; } const remotePort = await getPort(); - const remoteNode = await startEsNode(log, 'ftr-remote', { - ...config, - port: parseInt(new URL(config.ccsConfig.remoteClusterUrl).port, 10), - transportPort: remotePort, + const remoteNode = await startEsNode({ + log, + name: 'ftr-remote', + logsDir, + config: { + ...config, + port: parseInt(new URL(config.ccsConfig.remoteClusterUrl).port, 10), + transportPort: remotePort, + }, }); - const localNode = await startEsNode(log, 'ftr-local', { - ...config, - esArgs: [...config.esArgs, `cluster.remote.ftr-remote.seeds=localhost:${remotePort}`], + const localNode = await startEsNode({ + log, + name: 'ftr-local', + logsDir, + config: { + ...config, + esArgs: [...config.esArgs, `cluster.remote.ftr-remote.seeds=localhost:${remotePort}`], + }, }); return async () => { @@ -90,12 +106,19 @@ export async function runElasticsearch( }; } -async function startEsNode( - log: ToolingLog, - name: string, - config: EsConfig & { transportPort?: number }, - onEarlyExit?: (msg: string) => void -) { +async function startEsNode({ + log, + name, + config, + onEarlyExit, + logsDir, +}: { + log: ToolingLog; + name: string; + config: EsConfig & { transportPort?: number }; + onEarlyExit?: (msg: string) => void; + logsDir?: string; +}) { const cluster = createTestEsCluster({ clusterName: `cluster-${name}`, esArgs: config.esArgs, @@ -106,6 +129,7 @@ async function startEsNode( port: config.port, ssl: config.ssl, log, + writeLogsToPath: logsDir ? resolve(logsDir, `es-cluster-${name}.log`) : undefined, basePath: resolve(REPO_ROOT, '.es'), nodes: [ { diff --git a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts index 58b77151a9fdeb..2ae15ca5f83f86 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts +++ b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts @@ -42,7 +42,11 @@ export async function runKibanaServer({ }: { procs: ProcRunner; config: Config; - options: { installDir?: string; extraKbnOpts?: string[] }; + options: { + installDir?: string; + extraKbnOpts?: string[]; + logsDir?: string; + }; onEarlyExit?: (msg: string) => void; }) { const runOptions = config.get('kbnTestServer.runOptions'); @@ -84,10 +88,14 @@ export async function runKibanaServer({ ...(options.extraKbnOpts ?? []), ]); + const mainName = useTaskRunner ? 'kbn-ui' : 'kibana'; const promises = [ // main process - procs.run(useTaskRunner ? 'kbn-ui' : 'kibana', { + procs.run(mainName, { ...procRunnerOpts, + writeLogsToPath: options.logsDir + ? Path.resolve(options.logsDir, `${mainName}.log`) + : undefined, args: [ ...prefixArgs, ...parseRawFlags([ @@ -110,6 +118,9 @@ export async function runKibanaServer({ promises.push( procs.run('kbn-tasks', { ...procRunnerOpts, + writeLogsToPath: options.logsDir + ? Path.resolve(options.logsDir, 'kbn-tasks.log') + : undefined, args: [ ...prefixArgs, ...parseRawFlags([ diff --git a/packages/kbn-test/src/functional_tests/tasks.ts b/packages/kbn-test/src/functional_tests/tasks.ts index 9b5fb5424f3feb..26504b07544b0f 100644 --- a/packages/kbn-test/src/functional_tests/tasks.ts +++ b/packages/kbn-test/src/functional_tests/tasks.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import Fs from 'fs'; import Path from 'path'; import { setTimeout } from 'timers/promises'; @@ -51,6 +52,16 @@ const makeSuccessMessage = (options: StartServerOptions) => { ); }; +export async function initLogsDir(options: { logsDir?: string; createLogger(): ToolingLog }) { + if (options.logsDir) { + options + .createLogger() + .info(`Kibana/ES logs will be written to ${Path.relative(process.cwd(), options.logsDir)}/`); + + Fs.mkdirSync(options.logsDir, { recursive: true }); + } +} + /** * Run servers and tests for each config */ From 6bb83843fb1ed7e73f2f951df1e320c128d4d526 Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 9 Sep 2022 12:48:31 -0500 Subject: [PATCH 029/144] [ftr/detectionEngineApiIntegration] split group 1 (#140341) * [ftr/securitySolutions] split group 1 * add new ftr config to manifest --- .buildkite/ftr_configs.yml | 1 + .../security_and_spaces/group1/index.ts | 23 ----------- .../security_and_spaces/group10/config.ts | 18 ++++++++ .../create_signals_migrations.ts | 0 .../delete_signals_migrations.ts | 0 .../finalize_signals_migrations.ts | 0 .../get_rule_execution_results.ts | 0 .../get_signals_migration_status.ts | 0 .../{group1 => group10}/ignore_fields.ts | 0 .../import_export_rules.ts | 0 .../{group1 => group10}/import_rules.ts | 0 .../security_and_spaces/group10/index.ts | 41 +++++++++++++++++++ .../legacy_actions_migrations.ts | 0 .../{group1 => group10}/migrations.ts | 0 .../{group1 => group10}/open_close_signals.ts | 0 .../{group1 => group10}/patch_rules.ts | 0 .../{group1 => group10}/patch_rules_bulk.ts | 0 .../perform_bulk_action.ts | 0 .../perform_bulk_action_dry_run.ts | 0 .../{group1 => group10}/read_privileges.ts | 0 .../{group1 => group10}/read_rules.ts | 0 .../{group1 => group10}/resolve_read_rules.ts | 0 .../{group1 => group10}/runtime.ts | 0 .../template_data/execution_events.ts | 0 .../{group1 => group10}/throttle.ts | 0 .../{group1 => group10}/timestamps.ts | 0 .../{group1 => group10}/update_rules.ts | 0 .../{group1 => group10}/update_rules_bulk.ts | 0 28 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group10/config.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/create_signals_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/delete_signals_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/finalize_signals_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/get_rule_execution_results.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/get_signals_migration_status.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/ignore_fields.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/import_export_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/import_rules.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/legacy_actions_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/open_close_signals.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/patch_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/patch_rules_bulk.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/perform_bulk_action.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/perform_bulk_action_dry_run.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/read_privileges.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/read_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/resolve_read_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/runtime.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/template_data/execution_events.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/throttle.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/timestamps.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/update_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{group1 => group10}/update_rules_bulk.ts (100%) diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 812d22fec913bc..da3a104f9ca329 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -142,6 +142,7 @@ enabled: - x-pack/test/detection_engine_api_integration/security_and_spaces/group7/config.ts - x-pack/test/detection_engine_api_integration/security_and_spaces/group8/config.ts - x-pack/test/detection_engine_api_integration/security_and_spaces/group9/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group10/config.ts - x-pack/test/encrypted_saved_objects_api_integration/config.ts - x-pack/test/endpoint_api_integration_no_ingest/config.ts - x-pack/test/examples/config.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts index a857757f2d8643..3064d412da1bd6 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts @@ -34,28 +34,5 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./find_rule_exception_references')); loadTestFile(require.resolve('./generating_signals')); loadTestFile(require.resolve('./get_prepackaged_rules_status')); - loadTestFile(require.resolve('./get_rule_execution_results')); - loadTestFile(require.resolve('./import_rules')); - loadTestFile(require.resolve('./import_export_rules')); - loadTestFile(require.resolve('./legacy_actions_migrations')); - loadTestFile(require.resolve('./read_rules')); - loadTestFile(require.resolve('./resolve_read_rules')); - loadTestFile(require.resolve('./update_rules')); - loadTestFile(require.resolve('./update_rules_bulk')); - loadTestFile(require.resolve('./patch_rules_bulk')); - loadTestFile(require.resolve('./perform_bulk_action')); - loadTestFile(require.resolve('./perform_bulk_action_dry_run')); - loadTestFile(require.resolve('./patch_rules')); - loadTestFile(require.resolve('./read_privileges')); - loadTestFile(require.resolve('./open_close_signals')); - loadTestFile(require.resolve('./get_signals_migration_status')); - loadTestFile(require.resolve('./create_signals_migrations')); - loadTestFile(require.resolve('./finalize_signals_migrations')); - loadTestFile(require.resolve('./delete_signals_migrations')); - loadTestFile(require.resolve('./timestamps')); - loadTestFile(require.resolve('./runtime')); - loadTestFile(require.resolve('./throttle')); - loadTestFile(require.resolve('./ignore_fields')); - loadTestFile(require.resolve('./migrations')); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/config.ts new file mode 100644 index 00000000000000..2430b8f2148d9a --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/config.ts @@ -0,0 +1,18 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/create_signals_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_signals_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/create_signals_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/delete_signals_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_signals_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/delete_signals_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/finalize_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/finalize_signals_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/finalize_signals_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/finalize_signals_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_rule_execution_results.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/get_rule_execution_results.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_rule_execution_results.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/get_rule_execution_results.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_signals_migration_status.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/get_signals_migration_status.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_signals_migration_status.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/get_signals_migration_status.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/ignore_fields.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/ignore_fields.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/ignore_fields.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/ignore_fields.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_export_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_export_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_export_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_export_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts new file mode 100644 index 00000000000000..4449e9ca07800a --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts @@ -0,0 +1,41 @@ +/* + * 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 { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 10', function () { + // !!NOTE: For new routes that do any updates on a rule, please ensure that you are including the legacy + // action migration code. We are monitoring legacy action telemetry to clean up once we see their + // existence being near 0. + + loadTestFile(require.resolve('./get_rule_execution_results')); + loadTestFile(require.resolve('./import_rules')); + loadTestFile(require.resolve('./import_export_rules')); + loadTestFile(require.resolve('./legacy_actions_migrations')); + loadTestFile(require.resolve('./read_rules')); + loadTestFile(require.resolve('./resolve_read_rules')); + loadTestFile(require.resolve('./update_rules')); + loadTestFile(require.resolve('./update_rules_bulk')); + loadTestFile(require.resolve('./patch_rules_bulk')); + loadTestFile(require.resolve('./perform_bulk_action')); + loadTestFile(require.resolve('./perform_bulk_action_dry_run')); + loadTestFile(require.resolve('./patch_rules')); + loadTestFile(require.resolve('./read_privileges')); + loadTestFile(require.resolve('./open_close_signals')); + loadTestFile(require.resolve('./get_signals_migration_status')); + loadTestFile(require.resolve('./create_signals_migrations')); + loadTestFile(require.resolve('./finalize_signals_migrations')); + loadTestFile(require.resolve('./delete_signals_migrations')); + loadTestFile(require.resolve('./timestamps')); + loadTestFile(require.resolve('./runtime')); + loadTestFile(require.resolve('./throttle')); + loadTestFile(require.resolve('./ignore_fields')); + loadTestFile(require.resolve('./migrations')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/legacy_actions_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/legacy_actions_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/legacy_actions_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/legacy_actions_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/open_close_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/open_close_signals.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/open_close_signals.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/open_close_signals.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules_bulk.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules_bulk.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/patch_rules_bulk.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/perform_bulk_action.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/perform_bulk_action.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/perform_bulk_action_dry_run.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action_dry_run.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/perform_bulk_action_dry_run.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action_dry_run.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_privileges.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_privileges.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/resolve_read_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/resolve_read_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/resolve_read_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/resolve_read_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/runtime.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/runtime.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/template_data/execution_events.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/template_data/execution_events.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/template_data/execution_events.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/template_data/execution_events.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/throttle.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/throttle.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/throttle.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/throttle.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/timestamps.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/timestamps.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/timestamps.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/timestamps.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules_bulk.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts From 417957fb20f7692a842c84c949ccbee1c0251ab7 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:07:05 -0400 Subject: [PATCH 030/144] [Security Solution] Narrow test skips for Response actions in Responder (#140392) --- .../endpoint_responder/get_processes_action.test.tsx | 3 ++- .../endpoint_responder/kill_process_action.test.tsx | 3 ++- .../components/endpoint_responder/release_action.test.tsx | 6 +++--- .../endpoint_responder/suspend_process_action.test.tsx | 3 ++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/get_processes_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/get_processes_action.test.tsx index bb065a9392d435..29b6fd04465772 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/get_processes_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/get_processes_action.test.tsx @@ -194,7 +194,8 @@ describe('When using processes action from response actions console', () => { }); }); - it('should display completion output if done (no additional API calls)', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/139707 + it.skip('should display completion output if done (no additional API calls)', async () => { await render(); expect(apiMocks.responseProvider.actionDetails).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/kill_process_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/kill_process_action.test.tsx index 167c3feb554a75..827a4d61917541 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/kill_process_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/kill_process_action.test.tsx @@ -283,7 +283,8 @@ describe('When using the kill-process action from response actions console', () }); }); - it('should display completion output if done (no additional API calls)', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/139962 + it.skip('should display completion output if done (no additional API calls)', async () => { await render(); expect(apiMocks.responseProvider.actionDetails).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/release_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/release_action.test.tsx index e729185b220cc6..19e3be94469eb5 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/release_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/release_action.test.tsx @@ -20,8 +20,7 @@ import { getDeferred } from '../mocks'; import type { ResponderCapabilities } from '../../../../common/endpoint/constants'; import { RESPONDER_CAPABILITIES } from '../../../../common/endpoint/constants'; -// FLAKY: https://github.com/elastic/kibana/issues/139641 -describe.skip('When using the release action from response actions console', () => { +describe('When using the release action from response actions console', () => { let render: ( capabilities?: ResponderCapabilities[] ) => Promise>; @@ -205,7 +204,8 @@ describe.skip('When using the release action from response actions console', () }); }); - it('should display completion output if done (no additional API calls)', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/139641 + it.skip('should display completion output if done (no additional API calls)', async () => { await render(); expect(apiMocks.responseProvider.actionDetails).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/suspend_process_action.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/suspend_process_action.test.tsx index 4d12af721a02f5..9446fb5dcba6a7 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/suspend_process_action.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/suspend_process_action.test.tsx @@ -274,7 +274,8 @@ describe('When using the suspend-process action from response actions console', }); }); - it('should display completion output if done (no additional API calls)', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/140119 + it.skip('should display completion output if done (no additional API calls)', async () => { await render(); expect(apiMocks.responseProvider.actionDetails).toHaveBeenCalledTimes(1); From 6471ef75fe5b1eedf38520934e7f19b307c783d5 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:07:20 -0400 Subject: [PATCH 031/144] [Security Solution] Narrow test skips for Host Isolation Exceptions (#140396) --- .../view/components/form.test.tsx | 9 ++++++--- .../view/host_isolation_exceptions_list.test.tsx | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx index b60cdf6040b1d6..23f8ea83a70941 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx @@ -85,7 +85,8 @@ describe('When on the host isolation exceptions entry form', () => { await render(); }); - it('should render the form with empty inputs', () => { + // FLAKY: https://github.com/elastic/kibana/issues/140140 + it.skip('should render the form with empty inputs', () => { expect(renderResult.getByTestId('hostIsolationExceptions-form-name-input')).toHaveValue(''); expect(renderResult.getByTestId('hostIsolationExceptions-form-ip-input')).toHaveValue(''); expect( @@ -144,14 +145,16 @@ describe('When on the host isolation exceptions entry form', () => { ).toBe(true); }); - it('should show policy as selected when user clicks on it', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/139776 + it.skip('should show policy as selected when user clicks on it', async () => { userEvent.click(renderResult.getByTestId('perPolicy')); await clickOnEffectedPolicy(renderResult); await expect(isEffectedPolicySelected(renderResult)).resolves.toBe(true); }); - it('should retain the previous policy selection when switching from per-policy to global', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/139899 + it.skip('should retain the previous policy selection when switching from per-policy to global', async () => { // move to per-policy and select the first userEvent.click(renderResult.getByTestId('perPolicy')); await clickOnEffectedPolicy(renderResult); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx index ba830b859d0049..8fb3f683e6eb51 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx @@ -22,8 +22,7 @@ import { getFirstCard } from '../../../components/artifact_list_page/mocks'; jest.mock('../../../../common/components/user_privileges'); const useUserPrivilegesMock = _useUserPrivileges as jest.Mock; -// FLAKY: https://github.com/elastic/kibana/issues/135587 -describe.skip('When on the host isolation exceptions page', () => { +describe('When on the host isolation exceptions page', () => { let render: () => ReturnType; let renderResult: ReturnType; let history: AppContextTestRender['history']; @@ -78,7 +77,8 @@ describe.skip('When on the host isolation exceptions page', () => { ); }); - it('should hide the Create and Edit actions when host isolation authz is not allowed', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/135587 + it.skip('should hide the Create and Edit actions when host isolation authz is not allowed', async () => { // Use case: license downgrade scenario, where user still has entries defined, but no longer // able to create or edit them (only Delete them) const existingPrivileges = useUserPrivilegesMock(); From be580aaaff0b5d58eb597b42a6e77e1d7c4ae543 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:07:34 -0400 Subject: [PATCH 032/144] [Security Solution] Narrow test skips for Endpoint list management (#140398) --- .../endpoint_hosts/view/components/search_bar.test.tsx | 6 +++--- .../public/management/pages/index.test.tsx | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx index a2b7a8ad2ce2f0..eb651d8aedd12c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx @@ -16,8 +16,7 @@ import { fireEvent } from '@testing-library/dom'; import { uiQueryParams } from '../../store/selectors'; import type { EndpointIndexUIQueryParams } from '../../types'; -// FLAKY: https://github.com/elastic/kibana/issues/132398 -describe.skip('when rendering the endpoint list `AdminSearchBar`', () => { +describe('when rendering the endpoint list `AdminSearchBar`', () => { let render: ( urlParams?: EndpointIndexUIQueryParams ) => Promise>; @@ -85,7 +84,8 @@ describe.skip('when rendering the endpoint list `AdminSearchBar`', () => { expect(getQueryParamsFromStore().admin_query).toBe("(language:kuery,query:'host.name: foo')"); }); - it.each([ + // FLAKY: https://github.com/elastic/kibana/issues/132398 + it.skip.each([ ['nothing', ''], ['spaces', ' '], ])( diff --git a/x-pack/plugins/security_solution/public/management/pages/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/index.test.tsx index 7d2778d602c79e..1df471633c3c22 100644 --- a/x-pack/plugins/security_solution/public/management/pages/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/index.test.tsx @@ -16,8 +16,7 @@ import { endpointPageHttpMock } from './endpoint_hosts/mocks'; jest.mock('../../common/components/user_privileges'); -// FLAKY: https://github.com/elastic/kibana/issues/135166 -describe.skip('when in the Administration tab', () => { +describe('when in the Administration tab', () => { let render: () => ReturnType; beforeEach(() => { @@ -35,7 +34,8 @@ describe.skip('when in the Administration tab', () => { expect(await render().findByTestId('noIngestPermissions')).not.toBeNull(); }); - it('should display the Management view if user has privileges', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/135166 + it.skip('should display the Management view if user has privileges', async () => { (useUserPrivileges as jest.Mock).mockReturnValue({ endpointPrivileges: { loading: false, canAccessEndpointManagement: true }, }); From 9b28909a888dd7d00135ddb8acbf4e0a2b8169bb Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:07:55 -0400 Subject: [PATCH 033/144] [Security Solution] Narrow test skips in Policy list (#140407) --- .../pages/policy/view/policy_list.test.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx index 659e16dbd01290..5127f0605648ca 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx @@ -24,8 +24,7 @@ const getPackagePolicies = sendGetEndpointSpecificPackagePolicies as jest.Mock; const mockedSendBulkGetAgentPolicies = sendBulkGetAgentPolicyList as jest.Mock; -// FLAKY: https://github.com/elastic/kibana/issues/140153 -describe.skip('When on the policy list page', () => { +describe('When on the policy list page', () => { let render: () => ReturnType; let renderResult: ReturnType; let history: AppContextTestRender['history']; @@ -119,11 +118,15 @@ describe.skip('When on the policy list page', () => { expect(updatedByCells[0].textContent).toEqual(expectedAvatarName.charAt(0)); expect(firstUpdatedByName.textContent).toEqual(expectedAvatarName); }); - it('should show the correct endpoint count', async () => { + + // FLAKY: https://github.com/elastic/kibana/issues/139778 + it.skip('should show the correct endpoint count', async () => { const endpointCount = renderResult.getAllByTestId('policyEndpointCountLink'); expect(endpointCount[0].textContent).toBe('4'); }); - it('endpoint count link should navigate to the endpoint list filtered by policy', () => { + + // FLAKY: https://github.com/elastic/kibana/issues/140153 + it.skip('endpoint count link should navigate to the endpoint list filtered by policy', () => { const policyId = policies.items[0].id; const filterByPolicyQuery = `?admin_query=(language:kuery,query:'united.endpoint.Endpoint.policy.applied.id : "${policyId}"')`; const backLink = { @@ -186,7 +189,9 @@ describe.skip('When on the policy list page', () => { perPage: 10, }); }); - it('should pass the correct pageSize value to the api', async () => { + + // FLAKY: https://github.com/elastic/kibana/issues/139196 + it.skip('should pass the correct pageSize value to the api', async () => { await waitFor(() => { expect(renderResult.getByTestId('tablePaginationPopoverButton')).toBeTruthy(); }); @@ -206,7 +211,9 @@ describe.skip('When on the policy list page', () => { perPage: 20, }); }); - it('should call the api with the initial pagination values taken from the url', async () => { + + // FLAKY: https://github.com/elastic/kibana/issues/139207 + it.skip('should call the api with the initial pagination values taken from the url', async () => { act(() => { history.push('/administration/policies?page=3&pageSize=50'); }); From 89985e5289b4b1f4c9b6059f26d9c20a7765ac48 Mon Sep 17 00:00:00 2001 From: Rachel Shen Date: Fri, 9 Sep 2022 12:21:17 -0600 Subject: [PATCH 034/144] [Shared UX] Migrate router from kibana react to shared ux (#138544) --- package.json | 8 +- packages/shared-ux/router/impl/BUILD.bazel | 140 ++++++++++++++++++ packages/shared-ux/router/impl/README.mdx | 53 +++++++ .../impl/__snapshots__/router.test.tsx.snap | 35 +++++ packages/shared-ux/router/impl/index.ts | 9 ++ packages/shared-ux/router/impl/jest.config.js | 13 ++ packages/shared-ux/router/impl/package.json | 8 + .../shared-ux/router/impl/router.test.tsx | 45 ++++++ packages/shared-ux/router/impl/router.tsx | 78 ++++++++++ packages/shared-ux/router/impl/services.ts | 73 +++++++++ packages/shared-ux/router/impl/tsconfig.json | 19 +++ packages/shared-ux/router/impl/types.ts | 34 +++++ .../router/impl/use_execution_context.ts | 29 ++++ packages/shared-ux/router/mocks/BUILD.bazel | 135 +++++++++++++++++ packages/shared-ux/router/mocks/README.md | 3 + packages/shared-ux/router/mocks/index.ts | 11 ++ .../shared-ux/router/mocks/jest.config.js | 13 ++ packages/shared-ux/router/mocks/package.json | 8 + packages/shared-ux/router/mocks/src/index.ts | 10 ++ .../shared-ux/router/mocks/src/storybook.ts | 10 ++ packages/shared-ux/router/mocks/tsconfig.json | 20 +++ packages/shared-ux/router/types/BUILD.bazel | 60 ++++++++ packages/shared-ux/router/types/README.md | 3 + packages/shared-ux/router/types/index.d.ts | 7 + packages/shared-ux/router/types/package.json | 7 + packages/shared-ux/router/types/tsconfig.json | 14 ++ yarn.lock | 20 ++- 27 files changed, 861 insertions(+), 4 deletions(-) create mode 100644 packages/shared-ux/router/impl/BUILD.bazel create mode 100644 packages/shared-ux/router/impl/README.mdx create mode 100644 packages/shared-ux/router/impl/__snapshots__/router.test.tsx.snap create mode 100644 packages/shared-ux/router/impl/index.ts create mode 100644 packages/shared-ux/router/impl/jest.config.js create mode 100644 packages/shared-ux/router/impl/package.json create mode 100644 packages/shared-ux/router/impl/router.test.tsx create mode 100644 packages/shared-ux/router/impl/router.tsx create mode 100644 packages/shared-ux/router/impl/services.ts create mode 100644 packages/shared-ux/router/impl/tsconfig.json create mode 100644 packages/shared-ux/router/impl/types.ts create mode 100644 packages/shared-ux/router/impl/use_execution_context.ts create mode 100644 packages/shared-ux/router/mocks/BUILD.bazel create mode 100644 packages/shared-ux/router/mocks/README.md create mode 100644 packages/shared-ux/router/mocks/index.ts create mode 100644 packages/shared-ux/router/mocks/jest.config.js create mode 100644 packages/shared-ux/router/mocks/package.json create mode 100644 packages/shared-ux/router/mocks/src/index.ts create mode 100644 packages/shared-ux/router/mocks/src/storybook.ts create mode 100644 packages/shared-ux/router/mocks/tsconfig.json create mode 100644 packages/shared-ux/router/types/BUILD.bazel create mode 100644 packages/shared-ux/router/types/README.md create mode 100644 packages/shared-ux/router/types/index.d.ts create mode 100644 packages/shared-ux/router/types/package.json create mode 100644 packages/shared-ux/router/types/tsconfig.json diff --git a/package.json b/package.json index b223da37daa068..e53f8ed64b06b1 100644 --- a/package.json +++ b/package.json @@ -363,7 +363,9 @@ "@kbn/shared-ux-prompt-no-data-views": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/impl", "@kbn/shared-ux-prompt-no-data-views-mocks": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/mocks", "@kbn/shared-ux-prompt-no-data-views-types": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/types", - "@kbn/shared-ux-storybook-config": "link:bazel-bin/packages/shared-ux/storybook/config", + "@kbn/shared-ux-router-mocks": "link:bazel-bin/packages/shared-ux/router/mocks", + "@kbn/shared-ux-services": "link:bazel-bin/packages/kbn-shared-ux-services", + "@kbn/shared-ux-storybook": "link:bazel-bin/packages/kbn-shared-ux-storybook", "@kbn/shared-ux-storybook-mock": "link:bazel-bin/packages/shared-ux/storybook/mock", "@kbn/shared-ux-utility": "link:bazel-bin/packages/kbn-shared-ux-utility", "@kbn/std": "link:bazel-bin/packages/kbn-std", @@ -1077,7 +1079,9 @@ "@types/kbn__shared-ux-prompt-no-data-views": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/impl/npm_module_types", "@types/kbn__shared-ux-prompt-no-data-views-mocks": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/mocks/npm_module_types", "@types/kbn__shared-ux-prompt-no-data-views-types": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/types/npm_module_types", - "@types/kbn__shared-ux-storybook-config": "link:bazel-bin/packages/shared-ux/storybook/config/npm_module_types", + "@types/kbn__shared-ux-router-mocks": "link:bazel-bin/packages/shared-ux/router/mocks/npm_module_types", + "@types/kbn__shared-ux-services": "link:bazel-bin/packages/kbn-shared-ux-services/npm_module_types", + "@types/kbn__shared-ux-storybook": "link:bazel-bin/packages/kbn-shared-ux-storybook/npm_module_types", "@types/kbn__shared-ux-storybook-mock": "link:bazel-bin/packages/shared-ux/storybook/mock/npm_module_types", "@types/kbn__shared-ux-utility": "link:bazel-bin/packages/kbn-shared-ux-utility/npm_module_types", "@types/kbn__some-dev-log": "link:bazel-bin/packages/kbn-some-dev-log/npm_module_types", diff --git a/packages/shared-ux/router/impl/BUILD.bazel b/packages/shared-ux/router/impl/BUILD.bazel new file mode 100644 index 00000000000000..bc9b0aaac6d381 --- /dev/null +++ b/packages/shared-ux/router/impl/BUILD.bazel @@ -0,0 +1,140 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "shared-ux-router" +PKG_REQUIRE_NAME = "@kbn/shared-ux-router" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + "**/*.mdx" + ], + exclude = [ + "**/*.test.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +# In this array place runtime dependencies, including other packages and NPM packages +# which must be available for this code to run. +# +# To reference other packages use: +# "//repo/relative/path/to/package" +# eg. "//packages/kbn-utils" +# +# To reference a NPM package use: +# "@npm//name-of-package" +# eg. "@npm//lodash" +RUNTIME_DEPS = [ + "@npm//react", + "@npm//react-router-dom", + "@npm//react-use", + "@npm//rxjs", + "//packages/kbn-shared-ux-utility", + "//packages/kbn-test-jest-helpers", +] + +# In this array place dependencies necessary to build the types, which will include the +# :npm_module_types target of other packages and packages from NPM, including @types/* +# packages. +# +# To reference the types for another package use: +# "//repo/relative/path/to/package:npm_module_types" +# eg. "//packages/kbn-utils:npm_module_types" +# +# References to NPM packages work the same as RUNTIME_DEPS +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react", + "@npm//@types/react-router-dom", + "@npm//react-use", + "@npm//rxjs", + "//packages/kbn-shared-ux-utility:npm_module_types", + "//packages/shared-ux/router/types:npm_module_types", + "//packages/kbn-ambient-ui-types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, + additional_args = [ + "--copy-files", + "--quiet" + ], +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/shared-ux/router/impl/README.mdx b/packages/shared-ux/router/impl/README.mdx new file mode 100644 index 00000000000000..b8b0235e9a1e46 --- /dev/null +++ b/packages/shared-ux/router/impl/README.mdx @@ -0,0 +1,53 @@ +--- +id: sharedUX/Router +slug: /shared-ux/router +title: Router +description: A router component +tags: ['shared-ux', 'component', 'router', 'route'] +date: 2022-08-12 +--- + +## Summary +This is a wrapper around the `react-router-dom` Route component that inserts MatchPropagator in every application route. It helps track all route changes and send them to the execution context, later used to enrich APM 'route-change' transactions. +The component does not require any props and accepts props from the RouteProps interface such as a `path`, or a component like `AppContainer`. + + +```jsx + +``` + +### Explanation of RouteProps + +```jsx +export interface RouteProps { + location?: H.Location; + component?: React.ComponentType> | React.ComponentType; + render?: (props: RouteComponentProps) => React.ReactNode; + children?: ((props: RouteChildrenProps) => React.ReactNode) | React.ReactNode; + path?: string | string[]; + exact?: boolean; + sensitive?: boolean; + strict?: boolean; +} +``` + +All props are optional + +| Prop Name | Prop Type | Description | +|---|---|---| +| `location` | `H.Location` | the location of one instance of history | +| `component` | `React.ComponentType>` or `React.ComponentType;` | a react component | +| `render` | `(props: RouteComponentProps) => React.ReactNode;` | render props to a react node| +| `children` | `((props: RouteChildrenProps) => React.ReactNode)` or `React.ReactNode;` | pass children to a react node | +| `path` | `string` or `string[];` | a url path or array of paths | +| `exact` | `boolean` | exact match for a route (see: https://stackoverflow.com/questions/52275146/usage-of-exact-and-strict-props) | +| `sensitive` | `boolean` | case senstive route | +| `strict` | `boolean` | strict entry of the requested path in the path name | + + + +This component removes the need for manual calls to `useExecutionContext` and they should be removed. + +## EUI Promotion Status + +This component is not currently considered for promotion to EUI. \ No newline at end of file diff --git a/packages/shared-ux/router/impl/__snapshots__/router.test.tsx.snap b/packages/shared-ux/router/impl/__snapshots__/router.test.tsx.snap new file mode 100644 index 00000000000000..418aa60b7c1f4f --- /dev/null +++ b/packages/shared-ux/router/impl/__snapshots__/router.test.tsx.snap @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Route component prop renders 1`] = ` + +`; + +exports[`Route location renders as expected 1`] = ` + + + +`; + +exports[`Route render prop renders 1`] = ` + +`; + +exports[`Route renders 1`] = ` + + + +`; diff --git a/packages/shared-ux/router/impl/index.ts b/packages/shared-ux/router/impl/index.ts new file mode 100644 index 00000000000000..8659ff73ced365 --- /dev/null +++ b/packages/shared-ux/router/impl/index.ts @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { Route } from './router'; diff --git a/packages/shared-ux/router/impl/jest.config.js b/packages/shared-ux/router/impl/jest.config.js new file mode 100644 index 00000000000000..fe0025102d6550 --- /dev/null +++ b/packages/shared-ux/router/impl/jest.config.js @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/shared-ux/router/impl'], +}; diff --git a/packages/shared-ux/router/impl/package.json b/packages/shared-ux/router/impl/package.json new file mode 100644 index 00000000000000..3faa6ac609ebc0 --- /dev/null +++ b/packages/shared-ux/router/impl/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/shared-ux-router", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/shared-ux/router/impl/router.test.tsx b/packages/shared-ux/router/impl/router.test.tsx new file mode 100644 index 00000000000000..8c068d5a162d0e --- /dev/null +++ b/packages/shared-ux/router/impl/router.test.tsx @@ -0,0 +1,45 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { Component, FC } from 'react'; +import { shallow } from 'enzyme'; +import { Route } from './router'; +import { createMemoryHistory } from 'history'; + +describe('Route', () => { + test('renders', () => { + const example = shallow(); + expect(example).toMatchSnapshot(); + }); + + test('location renders as expected', () => { + // create a history + const historyLocation = createMemoryHistory(); + // add the path to the history + historyLocation.push('/app/wow'); + // prevent the location key from remaking itself each jest test + historyLocation.location.key = 's5brde'; + // the Route component takes the history location + const example = shallow(); + expect(example).toMatchSnapshot(); + }); + + test('component prop renders', () => { + const sampleComponent: FC<{}> = () => { + return Test; + }; + const example = shallow(); + expect(example).toMatchSnapshot(); + }); + + test('render prop renders', () => { + const sampleReactNode = React.createElement('li', { id: 'li1' }, 'one'); + const example = shallow( sampleReactNode} />); + expect(example).toMatchSnapshot(); + }); +}); diff --git a/packages/shared-ux/router/impl/router.tsx b/packages/shared-ux/router/impl/router.tsx new file mode 100644 index 00000000000000..da1dc2def3fc85 --- /dev/null +++ b/packages/shared-ux/router/impl/router.tsx @@ -0,0 +1,78 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useMemo } from 'react'; +import { + Route as ReactRouterRoute, + RouteComponentProps, + RouteProps, + useRouteMatch, +} from 'react-router-dom'; +import { useKibanaSharedUX } from './services'; +import { useSharedUXExecutionContext } from './use_execution_context'; + +/** + * This is a wrapper around the react-router-dom Route component that inserts + * MatchPropagator in every application route. It helps track all route changes + * and send them to the execution context, later used to enrich APM + * 'route-change' transactions. + */ +export const Route = ({ children, component: Component, render, ...rest }: RouteProps) => { + const component = useMemo(() => { + if (!Component) { + return undefined; + } + return (props: RouteComponentProps) => ( + <> + + + + ); + }, [Component]); + + if (component) { + return ; + } + if (render || typeof children === 'function') { + const renderFunction = typeof children === 'function' ? children : render; + return ( + ( + <> + + {/* @ts-ignore else condition exists if renderFunction is undefined*/} + {renderFunction(props)} + + )} + /> + ); + } + return ( + + + {children} + + ); +}; + +/** + * The match propogator that is part of the Route + */ +const MatchPropagator = () => { + const { executionContext } = useKibanaSharedUX().services; + const match = useRouteMatch(); + + useSharedUXExecutionContext(executionContext, { + type: 'application', + page: match.path, + id: Object.keys(match.params).length > 0 ? JSON.stringify(match.params) : undefined, + }); + + return null; +}; diff --git a/packages/shared-ux/router/impl/services.ts b/packages/shared-ux/router/impl/services.ts new file mode 100644 index 00000000000000..78150b576905b8 --- /dev/null +++ b/packages/shared-ux/router/impl/services.ts @@ -0,0 +1,73 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Observable } from 'rxjs'; +import { createContext, useContext } from 'react'; +import { SharedUXExecutionContext } from './types'; + +/** + * @public Execution context start and setup types are the same + */ +export declare type SharedUXExecutionContextStart = SharedUXExecutionContextSetup; + +/** + * Reduced the interface from ExecutionContextSetup from '@kbn/core-execution-context-browser' to only include properties needed for the Route + */ +export interface SharedUXExecutionContextSetup { + /** + * The current context observable + **/ + context$: Observable; + /** + * Set the current top level context + **/ + set(c$: SharedUXExecutionContext): void; + /** + * Get the current top level context + **/ + get(): SharedUXExecutionContext; + /** + * clears the context + **/ + clear(): void; +} + +/** + * Taken from Core services exposed to the `Plugin` start lifecycle + * + * @public + * + * @internalRemarks We document the properties with + * \@link tags to improve + * navigation in the generated docs until there's a fix for + * https://github.com/Microsoft/web-build-tools/issues/1237 + */ +export interface SharedUXExecutionContextSetup { + /** {@link SharedUXExecutionContextSetup} */ + executionContext: SharedUXExecutionContextStart; +} + +export type KibanaServices = Partial; + +export interface SharedUXRouterContextValue { + readonly services: Services; +} + +const defaultContextValue = { + services: {}, +}; + +export const sharedUXContext = + createContext>(defaultContextValue); + +export const useKibanaSharedUX = (): SharedUXRouterContextValue< + KibanaServices & Extra +> => + useContext( + sharedUXContext as unknown as React.Context> + ); diff --git a/packages/shared-ux/router/impl/tsconfig.json b/packages/shared-ux/router/impl/tsconfig.json new file mode 100644 index 00000000000000..764f1f42f52f9d --- /dev/null +++ b/packages/shared-ux/router/impl/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [ + "jest", + "node", + "react", + "@kbn/ambient-ui-types", + ] + }, + "include": [ + "**/*", + ] +} diff --git a/packages/shared-ux/router/impl/types.ts b/packages/shared-ux/router/impl/types.ts new file mode 100644 index 00000000000000..a76e8a87c4fe38 --- /dev/null +++ b/packages/shared-ux/router/impl/types.ts @@ -0,0 +1,34 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * @public + * Represents a meta-information about a Kibana entity initiating a search request. + */ +export declare interface SharedUXExecutionContext { + /** + * Kibana application initiated an operation. + * */ + readonly type?: string; + /** public name of an application or a user-facing feature */ + readonly name?: string; + /** a stand alone, logical unit such as an application page or tab */ + readonly page?: string; + /** unique value to identify the source */ + readonly id?: string; + /** human readable description. For example, a vis title, action name */ + readonly description?: string; + /** in browser - url to navigate to a current page, on server - endpoint path, for task: task SO url */ + readonly url?: string; + /** Metadata attached to the field. An optional parameter that allows to describe the execution context in more detail. **/ + readonly meta?: { + [key: string]: string | number | boolean | undefined; + }; + /** an inner context spawned from the current context. */ + child?: SharedUXExecutionContext; +} diff --git a/packages/shared-ux/router/impl/use_execution_context.ts b/packages/shared-ux/router/impl/use_execution_context.ts new file mode 100644 index 00000000000000..e2bb6168d12686 --- /dev/null +++ b/packages/shared-ux/router/impl/use_execution_context.ts @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import useDeepCompareEffect from 'react-use/lib/useDeepCompareEffect'; +import { SharedUXExecutionContextSetup } from './services'; +import { SharedUXExecutionContext } from './types'; + +/** + * Set and clean up application level execution context + * @param executionContext + * @param context + */ +export function useSharedUXExecutionContext( + executionContext: SharedUXExecutionContextSetup | undefined, + context: SharedUXExecutionContext +) { + useDeepCompareEffect(() => { + executionContext?.set(context); + + return () => { + executionContext?.clear(); + }; + }, [context]); +} diff --git a/packages/shared-ux/router/mocks/BUILD.bazel b/packages/shared-ux/router/mocks/BUILD.bazel new file mode 100644 index 00000000000000..248dd93ce803ba --- /dev/null +++ b/packages/shared-ux/router/mocks/BUILD.bazel @@ -0,0 +1,135 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "mocks" +PKG_REQUIRE_NAME = "@kbn/shared-ux-router-mocks" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__", + "**/integration_tests", + "**/mocks", + "**/scripts", + "**/storybook", + "**/test_fixtures", + "**/test_helpers", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +# In this array place runtime dependencies, including other packages and NPM packages +# which must be available for this code to run. +# +# To reference other packages use: +# "//repo/relative/path/to/package" +# eg. "//packages/kbn-utils" +# +# To reference a NPM package use: +# "@npm//name-of-package" +# eg. "@npm//lodash" +RUNTIME_DEPS = [ + "@npm//react" +] + +# In this array place dependencies necessary to build the types, which will include the +# :npm_module_types target of other packages and packages from NPM, including @types/* +# packages. +# +# To reference the types for another package use: +# "//repo/relative/path/to/package:npm_module_types" +# eg. "//packages/kbn-utils:npm_module_types" +# +# References to NPM packages work the same as RUNTIME_DEPS +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react" +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = ".", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/shared-ux/router/mocks/README.md b/packages/shared-ux/router/mocks/README.md new file mode 100644 index 00000000000000..4aa41535f4bb20 --- /dev/null +++ b/packages/shared-ux/router/mocks/README.md @@ -0,0 +1,3 @@ +# @kbn/shared-ux-router-mocks + +Empty package generated by @kbn/generate diff --git a/packages/shared-ux/router/mocks/index.ts b/packages/shared-ux/router/mocks/index.ts new file mode 100644 index 00000000000000..b6e7485e36ab2c --- /dev/null +++ b/packages/shared-ux/router/mocks/index.ts @@ -0,0 +1,11 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export function foo() { + return 'hello world'; +} diff --git a/packages/shared-ux/router/mocks/jest.config.js b/packages/shared-ux/router/mocks/jest.config.js new file mode 100644 index 00000000000000..9fbc3e5c702467 --- /dev/null +++ b/packages/shared-ux/router/mocks/jest.config.js @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/shared-ux/router/mocks'], +}; diff --git a/packages/shared-ux/router/mocks/package.json b/packages/shared-ux/router/mocks/package.json new file mode 100644 index 00000000000000..d089a5d01f1062 --- /dev/null +++ b/packages/shared-ux/router/mocks/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/shared-ux-router-mocks", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/shared-ux/router/mocks/src/index.ts b/packages/shared-ux/router/mocks/src/index.ts new file mode 100644 index 00000000000000..4687a8e2cb53f4 --- /dev/null +++ b/packages/shared-ux/router/mocks/src/index.ts @@ -0,0 +1,10 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { RouterMock } from './storybook'; +export type { RouterParams } from './storybook'; diff --git a/packages/shared-ux/router/mocks/src/storybook.ts b/packages/shared-ux/router/mocks/src/storybook.ts new file mode 100644 index 00000000000000..96c15d715cdee4 --- /dev/null +++ b/packages/shared-ux/router/mocks/src/storybook.ts @@ -0,0 +1,10 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const RouterMock = undefined; +export type RouterParams = undefined; diff --git a/packages/shared-ux/router/mocks/tsconfig.json b/packages/shared-ux/router/mocks/tsconfig.json new file mode 100644 index 00000000000000..a4f1ce7985a55b --- /dev/null +++ b/packages/shared-ux/router/mocks/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": ".", + "stripInternal": false, + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ] +} diff --git a/packages/shared-ux/router/types/BUILD.bazel b/packages/shared-ux/router/types/BUILD.bazel new file mode 100644 index 00000000000000..b33071f126efe8 --- /dev/null +++ b/packages/shared-ux/router/types/BUILD.bazel @@ -0,0 +1,60 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "types" +PKG_REQUIRE_NAME = "@kbn/shared-ux-router-types" + +SRCS = glob( + [ + "*.d.ts", + ] +) + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +# In this array place runtime dependencies, including other packages and NPM packages +# which must be available for this code to run. +# +# To reference other packages use: +# "//repo/relative/path/to/package" +# eg. "//packages/kbn-utils" +# +# To reference a NPM package use: +# "@npm//name-of-package" +# eg. "@npm//lodash" +RUNTIME_DEPS = [ +] + +js_library( + name = PKG_DIRNAME, + srcs = SRCS + NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS, + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +alias( + name = "npm_module_types", + actual = ":" + PKG_DIRNAME, + visibility = ["//visibility:public"], +) + diff --git a/packages/shared-ux/router/types/README.md b/packages/shared-ux/router/types/README.md new file mode 100644 index 00000000000000..ad806d7d070bd3 --- /dev/null +++ b/packages/shared-ux/router/types/README.md @@ -0,0 +1,3 @@ +# @kbn/shared-ux-router-types + +TODO: rshen91 diff --git a/packages/shared-ux/router/types/index.d.ts b/packages/shared-ux/router/types/index.d.ts new file mode 100644 index 00000000000000..5c2d5b68ae2e03 --- /dev/null +++ b/packages/shared-ux/router/types/index.d.ts @@ -0,0 +1,7 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ diff --git a/packages/shared-ux/router/types/package.json b/packages/shared-ux/router/types/package.json new file mode 100644 index 00000000000000..323e9848a50a7e --- /dev/null +++ b/packages/shared-ux/router/types/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/shared-ux-router-types", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/shared-ux/router/types/tsconfig.json b/packages/shared-ux/router/types/tsconfig.json new file mode 100644 index 00000000000000..1a57218f76493d --- /dev/null +++ b/packages/shared-ux/router/types/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [] + }, + "include": [ + "*.d.ts" + ] +} diff --git a/yarn.lock b/yarn.lock index e0a3b8f3a5627b..03e4ddaace0931 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3703,7 +3703,11 @@ version "0.0.0" uid "" -"@kbn/shared-ux-storybook-config@link:bazel-bin/packages/shared-ux/storybook/config": +"@kbn/shared-ux-router-mocks@link:bazel-bin/packages/shared-ux/router/mocks": + version "0.0.0" + uid "" + +"@kbn/shared-ux-services@link:bazel-bin/packages/kbn-shared-ux-services": version "0.0.0" uid "" @@ -3711,6 +3715,10 @@ version "0.0.0" uid "" +"@kbn/shared-ux-storybook@link:bazel-bin/packages/kbn-shared-ux-storybook": + version "0.0.0" + uid "" + "@kbn/shared-ux-utility@link:bazel-bin/packages/kbn-shared-ux-utility": version "0.0.0" uid "" @@ -7797,7 +7805,11 @@ version "0.0.0" uid "" -"@types/kbn__shared-ux-storybook-config@link:bazel-bin/packages/shared-ux/storybook/config/npm_module_types": +"@types/kbn__shared-ux-router-mocks@link:bazel-bin/packages/shared-ux/router/mocks/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__shared-ux-services@link:bazel-bin/packages/kbn-shared-ux-services/npm_module_types": version "0.0.0" uid "" @@ -7805,6 +7817,10 @@ version "0.0.0" uid "" +"@types/kbn__shared-ux-storybook@link:bazel-bin/packages/kbn-shared-ux-storybook/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__shared-ux-utility@link:bazel-bin/packages/kbn-shared-ux-utility/npm_module_types": version "0.0.0" uid "" From cbbb90ebc92a99aab6d13e36728bf161f1064229 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Fri, 9 Sep 2022 11:29:09 -0700 Subject: [PATCH 035/144] [Screenshotting] Remove loadDelay handling (#139972) * [Screenshotting] Remove loadDelay handling * polish diff * code improvement * remove default for loadDelay * fix snapshot --- docs/settings/reporting-settings.asciidoc | 2 +- x-pack/plugins/screenshotting/README.md | 1 - .../server/config/schema.test.ts | 2 - .../screenshotting/server/config/schema.ts | 4 +- .../server/screenshots/index.test.ts | 21 +++-- .../server/screenshots/index.ts | 1 - .../server/screenshots/observable.test.ts | 15 ++-- .../server/screenshots/observable.ts | 10 +-- .../server/screenshots/wait_for_render.ts | 76 +++++++------------ 9 files changed, 49 insertions(+), 83 deletions(-) diff --git a/docs/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc index 88fc015ac8b9a4..afdfbdfd02eb07 100644 --- a/docs/settings/reporting-settings.asciidoc +++ b/docs/settings/reporting-settings.asciidoc @@ -106,7 +106,7 @@ capturing the page with a screenshot. As a result, a download will be available, but there will likely be errors in the visualizations in the report. `xpack.screenshotting.capture.loadDelay`:: -deprecated:[8.0.0,This setting has no effect.] Specify the {time-units}[amount of time] before taking a screenshot when visualizations are not evented. All visualizations that ship with {kib} are evented, so this setting should not have much effect. If you are seeing empty images instead of visualizations, try increasing this value. Defaults to `3s`. *NOTE*: This setting exists for backwards compatibility, but is unused and therefore does not have an affect on reporting performance. +deprecated:[8.0.0,This setting has no effect.] Specify the {time-units}[amount of time] before taking a screenshot when visualizations are not evented. All visualizations that ship with {kib} are evented, so this setting should not have much effect. If you are seeing empty images instead of visualizations, try increasing this value. *NOTE*: This setting exists for backwards compatibility, but is unused and therefore does not have an affect on reporting performance. [float] [[reporting-chromium-settings]] diff --git a/x-pack/plugins/screenshotting/README.md b/x-pack/plugins/screenshotting/README.md index aefa4cc90762b5..3a3ea87448e647 100644 --- a/x-pack/plugins/screenshotting/README.md +++ b/x-pack/plugins/screenshotting/README.md @@ -89,7 +89,6 @@ Option | Required | Default | Description `layout` | no | `{}` | Page layout parameters describing characteristics of the capturing screenshot (e.g., dimensions, zoom, etc.). `request` | no | _none_ | Kibana Request reference to extract headers from. `timeouts` | no | _none_ | Timeouts for each phase of the screenshot. -`timeouts.loadDelay` | no | `3000` | The amount of time in milliseconds before taking a screenshot when visualizations are not evented. All visualizations that ship with Kibana are evented, so this setting should not have much effect. If you are seeing empty images instead of visualizations, try increasing this value. `timeouts.openUrl` | no | `60000` | The timeout in milliseconds to allow the Chromium browser to wait for the "Loading…" screen to dismiss and find the initial data for the page. If the time is exceeded, a screenshot is captured showing the current page, and the result structure contains an error message. `timeouts.renderComplete` | no | `30000` | The timeout in milliseconds to allow the Chromium browser to wait for all visualizations to fetch and render the data. If the time is exceeded, a screenshot is captured showing the current page, and the result structure contains an error message. `timeouts.waitForElements` | no | `30000` | The timeout in milliseconds to allow the Chromium browser to wait for all visualization panels to load on the page. If the time is exceeded, a screenshot is captured showing the current page, and the result structure contains an error message. diff --git a/x-pack/plugins/screenshotting/server/config/schema.test.ts b/x-pack/plugins/screenshotting/server/config/schema.test.ts index 58fb4b5ab559e8..c2febf59062490 100644 --- a/x-pack/plugins/screenshotting/server/config/schema.test.ts +++ b/x-pack/plugins/screenshotting/server/config/schema.test.ts @@ -20,7 +20,6 @@ describe('ConfigSchema', () => { }, }, "capture": Object { - "loadDelay": "PT3S", "timeouts": Object { "openUrl": "PT1M", "renderComplete": "PT30S", @@ -81,7 +80,6 @@ describe('ConfigSchema', () => { }, }, "capture": Object { - "loadDelay": "PT3S", "timeouts": Object { "openUrl": "PT1M", "renderComplete": "PT30S", diff --git a/x-pack/plugins/screenshotting/server/config/schema.ts b/x-pack/plugins/screenshotting/server/config/schema.ts index 1e103a6b6e4d08..4900a5c9d775e5 100644 --- a/x-pack/plugins/screenshotting/server/config/schema.ts +++ b/x-pack/plugins/screenshotting/server/config/schema.ts @@ -81,9 +81,7 @@ export const ConfigSchema = schema.object({ }), }), zoom: schema.number({ defaultValue: 2 }), - loadDelay: schema.oneOf([schema.number(), schema.duration()], { - defaultValue: moment.duration({ seconds: 3 }), - }), + loadDelay: schema.maybe(schema.oneOf([schema.number(), schema.duration()])), // deprecated, unused }), poolSize: schema.number({ defaultValue: 1, min: 1 }), }); diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts index 11ce25e0f86f13..70aca733a03d1f 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/index.test.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/index.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { Logger, PackageInfo } from '@kbn/core/server'; import { httpServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { lastValueFrom, of, throwError } from 'rxjs'; @@ -14,12 +15,11 @@ import { SCREENSHOTTING_EXPRESSION, SCREENSHOTTING_EXPRESSION_INPUT, } from '../../common'; -import type { CloudSetup } from '@kbn/cloud-plugin/server'; +import * as errors from '../../common/errors'; import type { HeadlessChromiumDriverFactory } from '../browsers'; import { createMockBrowserDriver, createMockBrowserDriverFactory } from '../browsers/mock'; import type { ConfigType } from '../config'; import type { PngScreenshotOptions } from '../formats'; -import * as errors from '../../common/errors'; import * as Layouts from '../layouts/create_layout'; import { createMockLayout } from '../layouts/mock'; import { CONTEXT_ELEMENTATTRIBUTES } from './constants'; @@ -72,7 +72,6 @@ describe('Screenshot Observable Pipeline', () => { waitForElements: 30000, renderComplete: 30000, }, - loadDelay: 5000000000, zoom: 2, }, networkPolicy: { enabled: false, rules: [] }, @@ -125,13 +124,13 @@ describe('Screenshot Observable Pipeline', () => { }); it('captures screenshot of an expression', async () => { - await screenshots - .getScreenshots({ + await lastValueFrom( + screenshots.getScreenshots({ ...options, expression: 'kibana', input: 'something', } as PngScreenshotOptions) - .toPromise(); + ); expect(driver.open).toHaveBeenCalledTimes(1); expect(driver.open).toHaveBeenCalledWith( @@ -148,7 +147,7 @@ describe('Screenshot Observable Pipeline', () => { describe('error handling', () => { it('recovers if waitForSelector fails', async () => { - driver.waitForSelector.mockImplementation((selectorArg: string) => { + driver.waitForSelector.mockImplementation(() => { throw new Error('Mock error!'); }); const result = await lastValueFrom( @@ -169,14 +168,14 @@ describe('Screenshot Observable Pipeline', () => { driverFactory.createPage.mockReturnValue( of({ driver, - error$: throwError('Instant timeout has fired!'), + error$: throwError(() => 'Instant timeout has fired!'), close: () => of({}), }) ); - await expect(screenshots.getScreenshots(options).toPromise()).rejects.toMatchInlineSnapshot( - `"Instant timeout has fired!"` - ); + await expect( + lastValueFrom(screenshots.getScreenshots(options)) + ).rejects.toMatchInlineSnapshot(`"Instant timeout has fired!"`); }); it(`uses defaults for element positions and size when Kibana page is not ready`, async () => { diff --git a/x-pack/plugins/screenshotting/server/screenshots/index.ts b/x-pack/plugins/screenshotting/server/screenshots/index.ts index 57f8440c348172..0c6c6f409f848a 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/index.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/index.ts @@ -203,7 +203,6 @@ export class Screenshots { openUrl: 60000, waitForElements: 30000, renderComplete: 30000, - loadDelay: 3000, }, urls: [], } diff --git a/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts b/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts index cb0fa6720ff7d6..363c30ad83f339 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/observable.test.ts @@ -6,7 +6,7 @@ */ import { loggingSystemMock } from '@kbn/core/server/mocks'; -import { interval, of, throwError } from 'rxjs'; +import { interval, lastValueFrom, of, throwError } from 'rxjs'; import { map } from 'rxjs/operators'; import { createMockBrowserDriver } from '../browsers/mock'; import type { ConfigType } from '../config'; @@ -26,7 +26,6 @@ describe('ScreenshotObservableHandler', () => { config = { capture: { timeouts: { openUrl: 30000, waitForElements: 30000, renderComplete: 30000 }, - loadDelay: 5000, zoom: 13, }, } as ConfigType; @@ -55,14 +54,14 @@ describe('ScreenshotObservableHandler', () => { }) ); - const testPipeline = () => test$.toPromise(); + const testPipeline = () => lastValueFrom(test$); await expect(testPipeline).rejects.toMatchInlineSnapshot( `[Error: Screenshotting encountered a timeout error: "Test Config" took longer than 0.2 seconds. You may need to increase "xpack.screenshotting.testConfig" in kibana.yml.]` ); }); it('catches other Errors', async () => { - const test$ = throwError(new Error(`Test Error to Throw`)).pipe( + const test$ = throwError(() => new Error(`Test Error to Throw`)).pipe( screenshots.waitUntil({ timeoutValue: 200, label: 'Test Config', @@ -70,7 +69,7 @@ describe('ScreenshotObservableHandler', () => { }) ); - const testPipeline = () => test$.toPromise(); + const testPipeline = () => lastValueFrom(test$); await expect(testPipeline).rejects.toMatchInlineSnapshot( `[Error: The "Test Config" phase encountered an error: Error: Test Error to Throw]` ); @@ -85,7 +84,7 @@ describe('ScreenshotObservableHandler', () => { }) ); - await expect(test$.toPromise()).resolves.toBe(`nice to see you`); + await expect(lastValueFrom(test$)).resolves.toBe(`nice to see you`); }); }); @@ -104,7 +103,7 @@ describe('ScreenshotObservableHandler', () => { }) ); - await expect(test$.toPromise()).rejects.toMatchInlineSnapshot( + await expect(lastValueFrom(test$)).rejects.toMatchInlineSnapshot( `[Error: Browser was closed unexpectedly! Check the server logs for more info.]` ); }); @@ -117,7 +116,7 @@ describe('ScreenshotObservableHandler', () => { }) ); - await expect(test$.toPromise()).resolves.toBe(234455); + await expect(lastValueFrom(test$)).resolves.toBe(234455); }); }); }); diff --git a/x-pack/plugins/screenshotting/server/screenshots/observable.ts b/x-pack/plugins/screenshotting/server/screenshots/observable.ts index efd0974612c59b..f5662ee920bf4b 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/observable.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/observable.ts @@ -124,7 +124,6 @@ const getTimeouts = (captureConfig: ConfigType['capture']) => ({ configValue: `xpack.screenshotting.capture.timeouts.renderComplete`, label: 'render complete', }, - loadDelay: toNumber(captureConfig.loadDelay), }); export class ScreenshotObservableHandler { @@ -132,7 +131,7 @@ export class ScreenshotObservableHandler { constructor( private readonly driver: HeadlessChromiumDriver, - private readonly config: ConfigType, + config: ConfigType, private readonly eventLogger: EventLogger, private readonly layout: Layout, private options: ScreenshotObservableOptions @@ -222,12 +221,7 @@ export class ScreenshotObservableHandler { throw error; } - await waitForRenderComplete( - driver, - eventLogger, - toNumber(this.config.capture.loadDelay), - layout - ); + await waitForRenderComplete(driver, eventLogger, layout); }).pipe( mergeMap(() => forkJoin({ diff --git a/x-pack/plugins/screenshotting/server/screenshots/wait_for_render.ts b/x-pack/plugins/screenshotting/server/screenshots/wait_for_render.ts index 8cf8174be152fc..ed4ad83736d42e 100644 --- a/x-pack/plugins/screenshotting/server/screenshots/wait_for_render.ts +++ b/x-pack/plugins/screenshotting/server/screenshots/wait_for_render.ts @@ -13,7 +13,6 @@ import { Actions, EventLogger } from './event_logger'; export const waitForRenderComplete = async ( browser: HeadlessChromiumDriver, eventLogger: EventLogger, - loadDelay: number, layout: Layout ) => { const spanEnd = eventLogger.logScreenshottingEvent( @@ -22,54 +21,35 @@ export const waitForRenderComplete = async ( 'wait' ); - return await browser - .evaluate( - { - fn: (selector, visLoadDelay) => { - // wait for visualizations to finish loading - const visualizations: NodeListOf = document.querySelectorAll(selector); - const visCount = visualizations.length; - const renderedTasks = []; - - function waitForRender(visualization: Element) { - return new Promise((resolve) => { - visualization.addEventListener('renderComplete', () => resolve()); - }); - } - - function waitForRenderDelay() { - return new Promise((resolve) => { - setTimeout(resolve, visLoadDelay); - }); + await browser.evaluate( + { + fn: async (selector) => { + const visualizations: NodeListOf = document.querySelectorAll(selector); + const visCount = visualizations.length; + const renderedTasks = []; + + function waitForRender(visualization: Element) { + return new Promise((resolve) => { + visualization.addEventListener('renderComplete', () => resolve()); + }); + } + + for (let i = 0; i < visCount; i++) { + const visualization = visualizations[i]; + const isRendered = visualization.getAttribute('data-render-complete'); + + if (isRendered === 'false') { + renderedTasks.push(waitForRender(visualization)); } + } - for (let i = 0; i < visCount; i++) { - const visualization = visualizations[i]; - const isRendered = visualization.getAttribute('data-render-complete'); - - if (isRendered === 'disabled') { - renderedTasks.push(waitForRenderDelay()); - } else if (isRendered === 'false') { - renderedTasks.push(waitForRender(visualization)); - } - } - - // The renderComplete fires before the visualizations are in the DOM, so - // we wait for the event loop to flush before telling reporting to continue. This - // seems to correct a timing issue that was causing reporting to occasionally - // capture the first visualization before it was actually in the DOM. - // Note: 100 proved too short, see https://github.com/elastic/kibana/issues/22581, - // bumping to 250. - const hackyWaitForVisualizations = () => new Promise((r) => setTimeout(r, 250)); - - return Promise.all(renderedTasks).then(hackyWaitForVisualizations); - }, - args: [layout.selectors.renderComplete, loadDelay], + return await Promise.all(renderedTasks); }, - { context: CONTEXT_WAITFORRENDER }, - eventLogger.kbnLogger - ) - .then(() => { - spanEnd(); - }); + args: [layout.selectors.renderComplete], + }, + { context: CONTEXT_WAITFORRENDER }, + eventLogger.kbnLogger + ); + + spanEnd(); }; From b36df1914bfec9aafe508060a6123c419278dac4 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:38:12 -0400 Subject: [PATCH 036/144] [Security Solution] Narrow test skips for Artifact list pages (#140401) --- .../artifact_list_page/artifact_list_page.test.tsx | 9 +++++---- .../components/artifact_delete_modal.test.ts | 6 ++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx index df23ac288806b2..86ec7431bd8011 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx @@ -16,8 +16,7 @@ import { getDeferred } from '../mocks'; jest.mock('../../../common/components/user_privileges'); -// FLAKY: https://github.com/elastic/kibana/issues/129837 -describe.skip('When using the ArtifactListPage component', () => { +describe('When using the ArtifactListPage component', () => { let render: ( props?: Partial ) => ReturnType; @@ -156,7 +155,8 @@ describe.skip('When using the ArtifactListPage component', () => { expect(getByTestId('testPage-flyout')).toBeTruthy(); }); - it('should display the Delete modal when delete action is clicked', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/129837 + it.skip('should display the Delete modal when delete action is clicked', async () => { const { getByTestId } = await renderWithListData(); await clickCardAction('delete'); @@ -227,7 +227,8 @@ describe.skip('When using the ArtifactListPage component', () => { }); }); - it('should persist policy filter to the URL params', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/129837 + it.skip('should persist policy filter to the URL params', async () => { const policyId = mockedApi.responseProvider.endpointPackagePolicyList().items[0].id; const firstPolicyTestId = `policiesSelector-popover-items-${policyId}`; diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_delete_modal.test.ts b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_delete_modal.test.ts index 497baa999cf2e5..d0fb3e3c59dfa5 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_delete_modal.test.ts +++ b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/components/artifact_delete_modal.test.ts @@ -77,12 +77,14 @@ describe('When displaying the Delete artifact modal in the Artifact List Page', 10000 ); - it('should show Cancel and Delete buttons enabled', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/139527 + it.skip('should show Cancel and Delete buttons enabled', async () => { expect(cancelButton).toBeEnabled(); expect(submitButton).toBeEnabled(); }); - it('should close modal if Cancel/Close buttons are clicked', async () => { + // FLAKY: https://github.com/elastic/kibana/issues/139528 + it.skip('should close modal if Cancel/Close buttons are clicked', async () => { userEvent.click(cancelButton); expect(renderResult.queryByTestId('testPage-deleteModal')).toBeNull(); From 4fa5518ee8e5219a846aff36253d482dabc550b5 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Fri, 9 Sep 2022 12:52:07 -0600 Subject: [PATCH 037/144] use separte colors for each geo field layer (#140344) --- x-pack/plugins/ml/public/maps/util.ts | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/public/maps/util.ts b/x-pack/plugins/ml/public/maps/util.ts index 51acd123398a78..9685d378556a1b 100644 --- a/x-pack/plugins/ml/public/maps/util.ts +++ b/x-pack/plugins/ml/public/maps/util.ts @@ -9,7 +9,10 @@ import { FeatureCollection, Feature, Geometry } from 'geojson'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { htmlIdGenerator } from '@elastic/eui'; import { FIELD_ORIGIN, STYLE_TYPE, LayerDescriptor } from '@kbn/maps-plugin/common'; -import { ESSearchSourceDescriptor } from '@kbn/maps-plugin/common/descriptor_types'; +import { + ESSearchSourceDescriptor, + VectorStyleDescriptor, +} from '@kbn/maps-plugin/common/descriptor_types'; import type { SerializableRecord } from '@kbn/utility-types'; import { fromKueryExpression, luceneStringToDsl, toElasticsearchQuery } from '@kbn/es-query'; import { ESSearchResponse } from '@kbn/core/types/elasticsearch'; @@ -20,6 +23,7 @@ import { formatHumanReadableDateTimeSeconds } from '../../common/util/date_utils import type { MlApiServices } from '../application/services/ml_api_service'; import { MLAnomalyDoc } from '../../common/types/anomalies'; import { SEARCH_QUERY_LANGUAGE } from '../../common/constants/search'; +import { tabColor } from '../../common/util/group_color_utils'; import { getIndexPattern } from '../application/explorer/reducers/explorer_reducer/get_index_pattern'; import { AnomalySource } from './anomaly_source'; import { SourceIndexGeoFields } from '../application/explorer/explorer_utils'; @@ -119,9 +123,28 @@ export function getInitialSourceIndexFieldLayers(sourceIndexWithGeoFields: Sourc const { dataViewId, geoFields } = sourceIndexWithGeoFields[index]; geoFields.forEach((geoField) => { + const color = tabColor(geoField); + initialLayers.push({ id: htmlIdGenerator()(), - type: LAYER_TYPE.MVT_VECTOR, + type: LAYER_TYPE.GEOJSON_VECTOR, + style: { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color, + }, + }, + lineColor: { + type: 'STATIC', + options: { + color, + }, + }, + }, + } as unknown as VectorStyleDescriptor, sourceDescriptor: { id: htmlIdGenerator()(), type: SOURCE_TYPES.ES_SEARCH, From 109fb0d53464e3e68edb42e97588da3903963d1d Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Fri, 9 Sep 2022 15:31:35 -0400 Subject: [PATCH 038/144] [Security Solution][Admin][Responder] Allow user to hold a key down for the responder (#139674) --- .../command_input/command_input.test.tsx | 19 +++++ .../components/command_input/key_capture.tsx | 82 +++++++++++-------- 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx index 04a57ad6ec9f67..4cb233ee0c4808 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx @@ -59,6 +59,20 @@ describe('When entering data into the Console input', () => { expect(getUserInputText()).toEqual('cm'); }); + it('should repeat letters if the user holds letter key down on the keyboard', () => { + render(); + enterCommand('{a>5/}', { inputOnly: true, useKeyboard: true }); + expect(getUserInputText()).toEqual('aaaaa'); + }); + + it('should not display command key names in the input, when command keys are used', () => { + render(); + enterCommand('{Meta>}', { inputOnly: true, useKeyboard: true }); + expect(getUserInputText()).toEqual(''); + enterCommand('{Shift>}A{/Shift}', { inputOnly: true, useKeyboard: true }); + expect(getUserInputText()).toEqual('A'); + }); + it('should display placeholder text when input area is blank', () => { render(); @@ -201,6 +215,11 @@ describe('When entering data into the Console input', () => { expect(getRightOfCursorText()).toEqual(''); }); + it('should clear the input if the user holds down the delete/backspace key', () => { + typeKeyboardKey('{backspace>7/}'); + expect(getUserInputText()).toEqual(''); + }); + it('should move cursor to the left', () => { typeKeyboardKey('{ArrowLeft}'); typeKeyboardKey('{ArrowLeft}'); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/key_capture.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/key_capture.tsx index a88cffed733a6f..b5c999427e1d41 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/key_capture.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/key_capture.tsx @@ -5,7 +5,12 @@ * 2.0. */ -import type { FormEventHandler, KeyboardEventHandler, MutableRefObject } from 'react'; +import type { + ClipboardEventHandler, + FormEventHandler, + KeyboardEventHandler, + MutableRefObject, +} from 'react'; import React, { memo, useCallback, useMemo, useRef, useState } from 'react'; import { pick } from 'lodash'; import styled from 'styled-components'; @@ -65,12 +70,11 @@ export const KeyCapture = memo(({ onCapture, focusRef, onStateC // We don't need the actual value that was last input in this component, because // `setLastInput()` is used with a function that returns the typed character. // This state is used like this: - // 1. user presses a keyboard key - // 2. `input` event is triggered - we store the letter typed - // 3. the next event to be triggered (after `input`) that we listen for is `keyup`, - // and when that is triggered, we take the input letter (already stored) and - // call `onCapture()` with it and then set the lastInput state back to an empty string - const [, setLastInput] = useState(''); + // 1. User presses a keyboard key down + // 2. We store the key that was pressed + // 3. When the 'keyup' event is triggered, we call `onCapture()` + // with all of the character that were entered + // 4. We set the last input back to an empty string const getTestId = useTestIdGenerator(useDataTestSubj()); const inputRef = useRef(null); const blurInputRef = useRef(null); @@ -96,15 +100,36 @@ export const KeyCapture = memo(({ onCapture, focusRef, onStateC [onStateChange] ); - const handleOnKeyUp = useCallback>( + const handleInputOnPaste = useCallback( (ev) => { - // There is a condition (still not clear how it is actually happening) where the `Enter` key - // event from the EuiSelectable component gets captured here by the Input. Its likely due to - // the sequence of events between keyup, focus and the Focus trap component having the - // `returnFocus` on by default. - // To avoid having that key Event from actually being processed, we check for this custom - // property on the event and skip processing it if we find it. This property is currently - // set by the CommandInputHistory (using EuiSelectable). + const value = ev.clipboardData.getData('text'); + ev.stopPropagation(); + + // hard-coded for use in onCapture and future keyboard functions + const metaKey = { + altKey: false, + ctrlKey: false, + key: 'Meta', + keyCode: 91, + metaKey: true, + repeat: false, + shiftKey: false, + }; + + onCapture({ + value, + eventDetails: metaKey, + }); + }, + [onCapture] + ); + + // 1. Determine if the key press is one that we need to store ex) letters, digits, values that we see + // 2. If the user clicks a key we don't need to store as text, but we need to do logic with ex) backspace, delete, l/r arrows, we must call onCapture + const handleOnKeyDown = useCallback( + (ev) => { + // checking to ensure that the key is not a control character + const newValue = /^[\w\d]{2}/.test(ev.key) ? '' : ev.key; // @ts-expect-error if (!isCapturing || ev._CONSOLE_IGNORE_KEY) { @@ -119,6 +144,11 @@ export const KeyCapture = memo(({ onCapture, focusRef, onStateC ev.stopPropagation(); + // allows for clipboard events to be captured via onPaste event handler + if (ev.metaKey || ev.ctrlKey) { + return; + } + const eventDetails = pick(ev, [ 'key', 'altKey', @@ -129,26 +159,14 @@ export const KeyCapture = memo(({ onCapture, focusRef, onStateC 'shiftKey', ]); - setLastInput((value) => { - onCapture({ - value, - eventDetails, - }); - - return ''; + onCapture({ + value: newValue, + eventDetails, }); }, [isCapturing, onCapture] ); - const handleOnInput = useCallback>((ev) => { - const newValue = ev.currentTarget.value; - - setLastInput((prevState) => { - return `${prevState || ''}${newValue}`; - }); - }, []); - const keyCaptureFocusMethods = useMemo(() => { return { focus: (force: boolean = false) => { @@ -183,10 +201,10 @@ export const KeyCapture = memo(({ onCapture, focusRef, onStateC spellCheck="false" value="" tabIndex={-1} - onInput={handleOnInput} - onKeyUp={handleOnKeyUp} + onKeyDown={handleOnKeyDown} onBlur={handleInputOnBlur} onFocus={handleInputOnFocus} + onPaste={handleInputOnPaste} onChange={NOOP} // this just silences Jest output warnings ref={inputRef} /> From 3f62679852aa5875b956ceff15eadc5a3f3b1819 Mon Sep 17 00:00:00 2001 From: Rashmi Kulkarni Date: Fri, 9 Sep 2022 13:49:55 -0700 Subject: [PATCH 039/144] timepicker change for tsvb_charts (#140230) * timepicker change * timepicker change * remove comments --- .../apps/visualize/group4/_tsvb_chart.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/functional/apps/visualize/group4/_tsvb_chart.ts b/test/functional/apps/visualize/group4/_tsvb_chart.ts index 013c0473a59b97..b71458c5c55273 100644 --- a/test/functional/apps/visualize/group4/_tsvb_chart.ts +++ b/test/functional/apps/visualize/group4/_tsvb_chart.ts @@ -18,17 +18,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const security = getService('security'); const kibanaServer = getService('kibanaServer'); - const { timePicker, visChart, visualBuilder, visualize, settings } = getPageObjects([ - 'timePicker', + const { visChart, visualBuilder, visualize, settings, common } = getPageObjects([ 'visChart', 'visualBuilder', 'visualize', 'settings', + 'common', ]); + const from = 'Sep 19, 2015 @ 06:31:44.000'; + const to = 'Sep 22, 2015 @ 18:31:44.000'; + describe('visual builder', function describeIndexTests() { before(async () => { await visualize.initTests(); + await common.setTime({ from, to }); }); beforeEach(async () => { @@ -36,6 +40,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ['kibana_admin', 'test_logstash_reader', 'kibana_sample_admin'], { skipBrowserRefresh: true } ); + await visualize.navigateToNewVisualization(); await visualize.clickVisualBuilder(); await visualBuilder.checkVisualBuilderIsPresent(); @@ -398,10 +403,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await visualBuilder.setMetricsDataTimerangeMode('Last value'); await visualBuilder.setDropLastBucket(true); await visualBuilder.clickDataTab('metric'); - await timePicker.setAbsoluteRange( - 'Sep 19, 2015 @ 06:31:44.000', - 'Sep 22, 2015 @ 18:31:44.000' - ); }); const switchIndexTest = async (useKibanaIndexes: boolean) => { @@ -435,10 +436,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await visualBuilder.clickPanelOptions('metric'); await visualBuilder.setMetricsDataTimerangeMode('Last value'); await visualBuilder.setDropLastBucket(true); - await timePicker.setAbsoluteRange( - 'Sep 19, 2015 @ 06:31:44.000', - 'Sep 22, 2015 @ 18:31:44.000' - ); }); it('should be able to switch to gte interval (>=2d)', async () => { From 80154397e0d8b4e86139c0a1bdada5c4cb7001eb Mon Sep 17 00:00:00 2001 From: Spencer Date: Fri, 9 Sep 2022 17:28:29 -0500 Subject: [PATCH 040/144] [ftr/o11yApp] remove custom timeout for navigation (#140453) * [ftr/o11yApp] remove custom timeout for navigation * add codeowners to test dir --- .github/CODEOWNERS | 1 + x-pack/test/functional/services/cases/navigation.ts | 2 +- .../test/observability_functional/apps/observability/index.ts | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9d53eb77959438..ebc25aadd21ac8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -109,6 +109,7 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/observability/public/pages/cases @elastic/actionable-observability /x-pack/plugins/observability/public/pages/rules @elastic/actionable-observability /x-pack/plugins/observability/public/pages/rule_details @elastic/actionable-observability +/x-pack/test/observability_functional @elastic/actionable-observability @elastic/unified-observability # Infra Monitoring /x-pack/plugins/infra/ @elastic/infra-monitoring-ui diff --git a/x-pack/test/functional/services/cases/navigation.ts b/x-pack/test/functional/services/cases/navigation.ts index a54be7896877ea..8d3ba0e73a24ca 100644 --- a/x-pack/test/functional/services/cases/navigation.ts +++ b/x-pack/test/functional/services/cases/navigation.ts @@ -14,7 +14,7 @@ export function CasesNavigationProvider({ getPageObject, getService }: FtrProvid return { async navigateToApp(app: string = 'cases', appSelector: string = 'cases-app') { await common.navigateToApp(app); - await testSubjects.existOrFail(appSelector, { timeout: 2000 }); + await testSubjects.existOrFail(appSelector); }, async navigateToConfigurationPage(app: string = 'cases', appSelector: string = 'cases-app') { diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index 60a4c2a571a1ca..b3acbf5f51a8a9 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -8,8 +8,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { - // FAILING: https://github.com/elastic/kibana/issues/140437 - describe.skip('ObservabilityApp', function () { + describe('ObservabilityApp', function () { loadTestFile(require.resolve('./pages/alerts')); loadTestFile(require.resolve('./pages/cases/case_details')); loadTestFile(require.resolve('./pages/alerts/add_to_case')); From 3d255ab49fed7d21f014cf09045b23632ef6297f Mon Sep 17 00:00:00 2001 From: John Dorlus Date: Fri, 9 Sep 2022 19:52:51 -0400 Subject: [PATCH 041/144] Removed comment of the issue that was referenced for the skip. But the tests were already skipped. (#140338) --- .../test/functional/apps/home/feature_controls/home_security.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/functional/apps/home/feature_controls/home_security.ts b/x-pack/test/functional/apps/home/feature_controls/home_security.ts index a48bc7651a1ed1..831f0475c2c11f 100644 --- a/x-pack/test/functional/apps/home/feature_controls/home_security.ts +++ b/x-pack/test/functional/apps/home/feature_controls/home_security.ts @@ -35,7 +35,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/logstash_functional'); }); - // https://github.com/elastic/kibana/issues/132628 describe('global all privileges', () => { before(async () => { await security.role.create('global_all_role', { From 8d87028ec12594a24ca07ca97a0a7bdf76fd1743 Mon Sep 17 00:00:00 2001 From: Davis McPhee Date: Fri, 9 Sep 2022 23:20:43 -0300 Subject: [PATCH 042/144] [Discover] Add support for noPadding option to Lens embeddable (#140442) --- .../public/embeddable/embeddable.test.tsx | 84 +++++++++++++++++++ .../lens/public/embeddable/embeddable.tsx | 14 +++- 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx index 863bc82485b81e..9eb79190d44e78 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx @@ -1415,4 +1415,88 @@ describe('embeddable', () => { expect(expressionRenderer).toHaveBeenCalledTimes(2); expect(expressionRenderer.mock.calls[1][0]!.expression).toBe(`edited`); }); + + it('should override noPadding in the display options if noPadding is set in the embeddable input', async () => { + expressionRenderer = jest.fn((_) => null); + + const visDocument: Document = { + state: { + visualization: {}, + datasourceStates: {}, + query: { query: '', language: 'lucene' }, + filters: [], + }, + references: [], + title: 'My title', + visualizationType: 'testVis', + }; + + const createEmbeddable = (noPadding?: boolean) => { + return new Embeddable( + { + timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, + attributeService: attributeServiceMockFromSavedVis(visDocument), + data: dataMock, + expressionRenderer, + basePath, + dataViews: {} as DataViewsContract, + capabilities: { + canSaveDashboards: true, + canSaveVisualizations: true, + discover: {}, + navLinks: {}, + }, + inspector: inspectorPluginMock.createStartContract(), + getTrigger, + theme: themeServiceMock.createStartContract(), + visualizationMap: { + [visDocument.visualizationType as string]: { + getDisplayOptions: () => ({ + noPadding: false, + }), + } as unknown as Visualization, + }, + datasourceMap: {}, + injectFilterReferences: jest.fn(mockInjectFilterReferences), + documentToExpression: () => + Promise.resolve({ + ast: { + type: 'expression', + chain: [ + { type: 'function', function: 'my', arguments: {} }, + { type: 'function', function: 'expression', arguments: {} }, + ], + }, + errors: undefined, + }), + uiSettings: { get: () => undefined } as unknown as IUiSettingsClient, + }, + { + timeRange: { + from: 'now-15m', + to: 'now', + }, + noPadding, + } as LensEmbeddableInput + ); + }; + + let embeddable = createEmbeddable(); + embeddable.render(mountpoint); + + // wait one tick to give embeddable time to initialize + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(expressionRenderer).toHaveBeenCalledTimes(1); + expect(expressionRenderer.mock.calls[0][0]!.padding).toBe('s'); + + embeddable = createEmbeddable(true); + embeddable.render(mountpoint); + + // wait one tick to give embeddable time to initialize + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(expressionRenderer).toHaveBeenCalledTimes(2); + expect(expressionRenderer.mock.calls[1][0]!.padding).toBe(undefined); + }); }); diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 0e4c0594db3c47..fb7d7646871c70 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -103,6 +103,7 @@ interface LensBaseEmbeddableInput extends EmbeddableInput { renderMode?: RenderMode; style?: React.CSSProperties; className?: string; + noPadding?: boolean; onBrushEnd?: (data: BrushTriggerEvent['data']) => void; onLoad?: (isLoading: boolean, adapters?: Partial) => void; onFilter?: (data: ClickTriggerEvent['data']) => void; @@ -1016,6 +1017,17 @@ export class Embeddable ) { return; } - return this.deps.visualizationMap[this.savedVis.visualizationType].getDisplayOptions!(); + + let displayOptions = + this.deps.visualizationMap[this.savedVis.visualizationType].getDisplayOptions!(); + + if (this.input.noPadding !== undefined) { + displayOptions = { + ...displayOptions, + noPadding: this.input.noPadding, + }; + } + + return displayOptions; } } From 2788d86e7ab103862a7618366099e660672e3728 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 9 Sep 2022 22:41:39 -0600 Subject: [PATCH 043/144] [api-docs] Daily api_docs build (#140460) --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.devdocs.json | 21 + api_docs/alerting.mdx | 4 +- api_docs/apm.devdocs.json | 82 +++- api_docs/apm.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/core.devdocs.json | 124 +++-- api_docs/core.mdx | 4 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 4 +- api_docs/deprecations_by_plugin.mdx | 10 +- api_docs/deprecations_by_team.mdx | 4 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.devdocs.json | 118 +++++ api_docs/event_log.mdx | 4 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- api_docs/kbn_alerts.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.devdocs.json | 140 +----- api_docs/kbn_core_base_common.mdx | 7 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- .../kbn_core_injected_metadata_browser.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...core_saved_objects_api_server_internal.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.devdocs.json | 242 ++++++++++ api_docs/kbn_core_status_common.mdx | 36 ++ ...n_core_status_common_internal.devdocs.json | 355 ++++++++++++++ api_docs/kbn_core_status_common_internal.mdx | 33 ++ api_docs/kbn_core_status_server.devdocs.json | 378 +++++++++++++++ api_docs/kbn_core_status_server.mdx | 36 ++ ...n_core_status_server_internal.devdocs.json | 440 ++++++++++++++++++ api_docs/kbn_core_status_server_internal.mdx | 42 ++ .../kbn_core_status_server_mocks.devdocs.json | 94 ++++ api_docs/kbn_core_status_server_mocks.mdx | 30 ++ ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_internal.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_get_repo_files.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- ...hared_ux_button_exit_full_screen_mocks.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_router.devdocs.json | 65 +++ api_docs/kbn_shared_ux_router.mdx | 30 ++ .../kbn_shared_ux_router_mocks.devdocs.json | 45 ++ api_docs/kbn_shared_ux_router_mocks.mdx | 30 ++ api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_package_json.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.devdocs.json | 14 + api_docs/kbn_test.mdx | 4 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_type_summarizer.mdx | 2 +- api_docs/kbn_type_summarizer_core.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/observability.devdocs.json | 4 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 23 +- api_docs/presentation_util.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_field_list.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 396 files changed, 2588 insertions(+), 567 deletions(-) create mode 100644 api_docs/kbn_core_status_common.devdocs.json create mode 100644 api_docs/kbn_core_status_common.mdx create mode 100644 api_docs/kbn_core_status_common_internal.devdocs.json create mode 100644 api_docs/kbn_core_status_common_internal.mdx create mode 100644 api_docs/kbn_core_status_server.devdocs.json create mode 100644 api_docs/kbn_core_status_server.mdx create mode 100644 api_docs/kbn_core_status_server_internal.devdocs.json create mode 100644 api_docs/kbn_core_status_server_internal.mdx create mode 100644 api_docs/kbn_core_status_server_mocks.devdocs.json create mode 100644 api_docs/kbn_core_status_server_mocks.mdx create mode 100644 api_docs/kbn_shared_ux_router.devdocs.json create mode 100644 api_docs/kbn_shared_ux_router.mdx create mode 100644 api_docs/kbn_shared_ux_router_mocks.devdocs.json create mode 100644 api_docs/kbn_shared_ux_router_mocks.mdx diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 7b77296a7abb9d..d5c6c13ca391b5 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 8497e2ae833d52..7133dfd6c85cd3 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 28fd735f6e461e..dc7c5c036cacce 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index 5eecc7808e3037..21eec3051632eb 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -2810,6 +2810,16 @@ "section": "def-common.IExecutionLogResult", "text": "IExecutionLogResult" }, + ">; getGlobalExecutionLogWithAuth: ({ dateStart, dateEnd, filter, page, perPage, sort, }: ", + "GetGlobalExecutionLogParams", + ") => Promise<", + { + "pluginId": "alerting", + "scope": "common", + "docId": "kibAlertingPluginApi", + "section": "def-common.IExecutionLogResult", + "text": "IExecutionLogResult" + }, ">; getActionErrorLog: ({ id, dateStart, dateEnd, filter, page, perPage, sort, }: ", "GetActionErrorLogByIdParams", ") => Promise<", @@ -4128,6 +4138,17 @@ "path": "x-pack/plugins/alerting/common/execution_log_types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "alerting", + "id": "def-common.IExecutionLog.rule_id", + "type": "string", + "tags": [], + "label": "rule_id", + "description": [], + "path": "x-pack/plugins/alerting/common/execution_log_types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index d331897a74bc21..445e6f8b161d04 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 368 | 0 | 359 | 21 | +| 369 | 0 | 360 | 22 | ## Client diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index efaf84a5b304a1..6c0d9f74ea5804 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -792,7 +792,7 @@ "label": "APIEndpoint", "description": [], "signature": [ - "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\"" + "\"POST /internal/apm/data_view/static\" | \"GET /internal/apm/data_view/title\" | \"GET /internal/apm/environments\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/groups/main_statistics_by_transaction_name\" | \"POST /internal/apm/services/{serviceName}/errors/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}\" | \"GET /internal/apm/services/{serviceName}/errors/distribution\" | \"GET /internal/apm/services/{serviceName}/errors/{groupId}/top_erroneous_transactions\" | \"POST /internal/apm/latency/overall_distribution/transactions\" | \"GET /internal/apm/services/{serviceName}/metrics/charts\" | \"GET /internal/apm/observability_overview\" | \"GET /internal/apm/observability_overview/has_data\" | \"GET /internal/apm/service-map\" | \"GET /internal/apm/service-map/service/{serviceName}\" | \"GET /internal/apm/service-map/dependency\" | \"GET /internal/apm/services/{serviceName}/serviceNodes\" | \"GET /internal/apm/services\" | \"POST /internal/apm/services/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/metadata/details\" | \"GET /internal/apm/services/{serviceName}/metadata/icons\" | \"GET /internal/apm/services/{serviceName}/agent\" | \"GET /internal/apm/services/{serviceName}/transaction_types\" | \"GET /internal/apm/services/{serviceName}/node/{serviceNodeName}/metadata\" | \"GET /api/apm/services/{serviceName}/annotation/search\" | \"POST /api/apm/services/{serviceName}/annotation\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/details/{serviceNodeName}\" | \"GET /internal/apm/services/{serviceName}/throughput\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics\" | \"GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/dependencies\" | \"GET /internal/apm/services/{serviceName}/dependencies/breakdown\" | \"GET /internal/apm/services/{serviceName}/profiling/timeline\" | \"GET /internal/apm/services/{serviceName}/profiling/statistics\" | \"GET /internal/apm/services/{serviceName}/anomaly_charts\" | \"GET /internal/apm/sorted_and_filtered_services\" | \"GET /internal/apm/service-groups\" | \"GET /internal/apm/service-group\" | \"POST /internal/apm/service-group\" | \"DELETE /internal/apm/service-group\" | \"GET /internal/apm/service-group/services\" | \"GET /internal/apm/suggestions\" | \"GET /internal/apm/traces/{traceId}\" | \"GET /internal/apm/traces\" | \"GET /internal/apm/traces/{traceId}/root_transaction\" | \"GET /internal/apm/transactions/{transactionId}\" | \"GET /internal/apm/traces/find\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/latency\" | \"GET /internal/apm/services/{serviceName}/transactions/traces/samples\" | \"GET /internal/apm/services/{serviceName}/transaction/charts/breakdown\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/error_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate\" | \"GET /internal/apm/services/{serviceName}/transactions/charts/coldstart_rate_by_transaction_name\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_rate\" | \"GET /internal/apm/alerts/chart_preview/transaction_duration\" | \"GET /internal/apm/alerts/chart_preview/transaction_error_count\" | \"GET /api/apm/settings/agent-configuration\" | \"GET /api/apm/settings/agent-configuration/view\" | \"DELETE /api/apm/settings/agent-configuration\" | \"PUT /api/apm/settings/agent-configuration\" | \"POST /api/apm/settings/agent-configuration/search\" | \"GET /api/apm/settings/agent-configuration/environments\" | \"GET /api/apm/settings/agent-configuration/agent_name\" | \"GET /internal/apm/settings/anomaly-detection/jobs\" | \"POST /internal/apm/settings/anomaly-detection/jobs\" | \"GET /internal/apm/settings/anomaly-detection/environments\" | \"POST /internal/apm/settings/anomaly-detection/update_to_v3\" | \"GET /internal/apm/settings/apm-index-settings\" | \"GET /internal/apm/settings/apm-indices\" | \"POST /internal/apm/settings/apm-indices/save\" | \"GET /internal/apm/settings/custom_links/transaction\" | \"GET /internal/apm/settings/custom_links\" | \"POST /internal/apm/settings/custom_links\" | \"PUT /internal/apm/settings/custom_links/{id}\" | \"DELETE /internal/apm/settings/custom_links/{id}\" | \"GET /api/apm/sourcemaps\" | \"POST /api/apm/sourcemaps\" | \"DELETE /api/apm/sourcemaps/{id}\" | \"GET /internal/apm/fleet/has_apm_policies\" | \"GET /internal/apm/fleet/agents\" | \"POST /api/apm/fleet/apm_server_schema\" | \"GET /internal/apm/fleet/apm_server_schema/unsupported\" | \"GET /internal/apm/fleet/migration_check\" | \"POST /internal/apm/fleet/cloud_apm_package_policy\" | \"GET /internal/apm/fleet/java_agent_versions\" | \"GET /internal/apm/dependencies/top_dependencies\" | \"GET /internal/apm/dependencies/upstream_services\" | \"GET /internal/apm/dependencies/metadata\" | \"GET /internal/apm/dependencies/charts/latency\" | \"GET /internal/apm/dependencies/charts/throughput\" | \"GET /internal/apm/dependencies/charts/error_rate\" | \"GET /internal/apm/dependencies/operations\" | \"GET /internal/apm/dependencies/charts/distribution\" | \"GET /internal/apm/dependencies/operations/spans\" | \"GET /internal/apm/correlations/field_candidates/transactions\" | \"POST /internal/apm/correlations/field_stats/transactions\" | \"GET /internal/apm/correlations/field_value_stats/transactions\" | \"POST /internal/apm/correlations/field_value_pairs/transactions\" | \"POST /internal/apm/correlations/significant_correlations/transactions\" | \"POST /internal/apm/correlations/p_values/transactions\" | \"GET /internal/apm/fallback_to_transactions\" | \"GET /internal/apm/has_data\" | \"GET /internal/apm/event_metadata/{processorEvent}/{id}\" | \"GET /internal/apm/agent_keys\" | \"GET /internal/apm/agent_keys/privileges\" | \"POST /internal/apm/api_key/invalidate\" | \"POST /api/apm/agent_keys\" | \"GET /internal/apm/storage_explorer\" | \"GET /internal/apm/services/{serviceName}/storage_details\" | \"GET /internal/apm/storage_chart\" | \"GET /internal/apm/storage_explorer/privileges\" | \"GET /internal/apm/storage_explorer_summary_stats\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/parents\" | \"GET /internal/apm/traces/{traceId}/span_links/{spanId}/children\" | \"GET /internal/apm/services/{serviceName}/infrastructure_attributes\" | \"GET /internal/apm/debug-telemetry\" | \"GET /internal/apm/time_range_metadata\"" ], "path": "x-pack/plugins/apm/server/routes/apm_routes/get_global_apm_server_route_repository.ts", "deprecated": false, @@ -1064,6 +1064,86 @@ "SpanLinkDetails", "[]; }, ", "APMRouteCreateOptions", + ">; \"GET /internal/apm/storage_explorer_summary_stats\": ", + "ServerRoute", + "<\"GET /internal/apm/storage_explorer_summary_stats\", ", + "TypeC", + "<{ query: ", + "IntersectionC", + "<[", + "TypeC", + "<{ indexLifecyclePhase: ", + "UnionC", + "<[", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".All>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Hot>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Warm>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Cold>, ", + "LiteralC", + "<", + "IndexLifecyclePhaseSelectOption", + ".Frozen>]>; }>, ", + "TypeC", + "<{ probability: ", + "Type", + "; }>, ", + "TypeC", + "<{ environment: ", + "UnionC", + "<[", + "LiteralC", + "<\"ENVIRONMENT_NOT_DEFINED\">, ", + "LiteralC", + "<\"ENVIRONMENT_ALL\">, ", + "BrandC", + "<", + "StringC", + ", ", + "NonEmptyStringBrand", + ">]>; }>, ", + "TypeC", + "<{ kuery: ", + "StringC", + "; }>, ", + "TypeC", + "<{ start: ", + "Type", + "; end: ", + "Type", + "; }>]>; }>, ", + { + "pluginId": "apm", + "scope": "server", + "docId": "kibApmPluginApi", + "section": "def-server.APMRouteHandlerResources", + "text": "APMRouteHandlerResources" + }, + ", { tracesPerMinute: number; numberOfServices: number; estimatedSize: number; dailyDataGeneration: number; }, ", + "APMRouteCreateOptions", + ">; \"GET /internal/apm/storage_explorer/privileges\": ", + "ServerRoute", + "<\"GET /internal/apm/storage_explorer/privileges\", undefined, ", + { + "pluginId": "apm", + "scope": "server", + "docId": "kibApmPluginApi", + "section": "def-server.APMRouteHandlerResources", + "text": "APMRouteHandlerResources" + }, + ", { hasPrivileges: boolean; }, ", + "APMRouteCreateOptions", ">; \"GET /internal/apm/storage_chart\": ", "ServerRoute", "<\"GET /internal/apm/storage_chart\", ", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 27c873e1cbc08c..87a44cde46dfc8 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 167582665bb6d3..fecb09b91403a3 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 363cb213dfa2c9..31934ad54f169d 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index 2910180b02cdf0..b65e73ac957fd4 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index cbc8bc0dcfd440..4ab29be190d884 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index ca9fc19e1213bb..f280cd886f8075 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index bffc54e20d6abc..7647e574a0489e 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 40ee284d2734c8..d700f715cd5fcb 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 88390589d38352..596ad1ce6d85d9 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index ae609d41255ab2..4f085837f13179 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.devdocs.json b/api_docs/core.devdocs.json index 35d2b408052f50..44e4755f2f47d4 100644 --- a/api_docs/core.devdocs.json +++ b/api_docs/core.devdocs.json @@ -576,6 +576,10 @@ "plugin": "@kbn/core-analytics-server-internal", "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, { "plugin": "security", "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" @@ -588,6 +592,18 @@ "plugin": "@kbn/core-analytics-server-mocks", "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, { "plugin": "@kbn/core-analytics-browser-mocks", "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" @@ -918,6 +934,10 @@ "plugin": "@kbn/core-execution-context-browser-internal", "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, { "plugin": "cloud", "path": "x-pack/plugins/cloud/public/plugin.test.ts" @@ -982,6 +1002,14 @@ "plugin": "@kbn/core-elasticsearch-server-internal", "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, { "plugin": "@kbn/core-analytics-browser-internal", "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" @@ -18603,6 +18631,10 @@ "plugin": "@kbn/core-analytics-server-internal", "path": "packages/core/analytics/core-analytics-server-internal/src/analytics_service.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, { "plugin": "security", "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" @@ -18615,6 +18647,18 @@ "plugin": "@kbn/core-analytics-server-mocks", "path": "packages/core/analytics/core-analytics-server-mocks/src/analytics_service.mock.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, { "plugin": "@kbn/core-analytics-browser-mocks", "path": "packages/core/analytics/core-analytics-browser-mocks/src/analytics_service.mock.ts" @@ -18945,6 +18989,10 @@ "plugin": "@kbn/core-execution-context-browser-internal", "path": "packages/core/execution-context/core-execution-context-browser-internal/src/execution_context_service.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.ts" + }, { "plugin": "cloud", "path": "x-pack/plugins/cloud/public/plugin.test.ts" @@ -19009,6 +19057,14 @@ "plugin": "@kbn/core-elasticsearch-server-internal", "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/register_analytics_context_provider.test.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/status_service.test.ts" + }, { "plugin": "@kbn/core-analytics-browser-internal", "path": "packages/core/analytics/core-analytics-browser-internal/src/analytics_service.test.mocks.ts" @@ -21123,13 +21179,7 @@ "{@link StatusServiceSetup}" ], "signature": [ - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.StatusServiceSetup", - "text": "StatusServiceSetup" - } + "StatusServiceSetup" ], "path": "src/core/server/index.ts", "deprecated": false, @@ -21383,7 +21433,10 @@ "description": [ "\nStatus of core services.\n" ], - "path": "src/core/server/status/types.ts", + "signature": [ + "CoreStatus" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -21398,7 +21451,7 @@ "ServiceStatus", "" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -21413,7 +21466,7 @@ "ServiceStatus", "" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false } @@ -36027,6 +36080,14 @@ "plugin": "@kbn/core-metrics-server-internal", "path": "packages/core/metrics/core-metrics-server-internal/src/logging/get_ops_metrics_log.ts" }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/routes/status.ts" + }, + { + "plugin": "@kbn/core-status-server-internal", + "path": "packages/core/status/core-status-server-internal/src/routes/status.ts" + }, { "plugin": "@kbn/core-usage-data-server-internal", "path": "packages/core/usage-data/core-usage-data-server-internal/src/core_usage_data_service.ts" @@ -46420,7 +46481,7 @@ "ServiceStatus", "" ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -46436,7 +46497,7 @@ "signature": [ "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -46449,7 +46510,7 @@ "description": [ "\nA high-level summary of the service status." ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -46465,7 +46526,7 @@ "signature": [ "string | undefined" ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -46481,7 +46542,7 @@ "signature": [ "string | undefined" ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -46497,7 +46558,7 @@ "signature": [ "Meta | undefined" ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false } @@ -46906,7 +46967,10 @@ "description": [ "\nAPI for accessing status of Core and this plugin's dependencies as well as for customizing this plugin's status.\n" ], - "path": "src/core/server/status/types.ts", + "signature": [ + "StatusServiceSetup" + ], + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -46922,16 +46986,10 @@ "signature": [ "Observable", "<", - { - "pluginId": "core", - "scope": "server", - "docId": "kibCorePluginApi", - "section": "def-server.CoreStatus", - "text": "CoreStatus" - }, + "CoreStatus", ">" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -46950,7 +47008,7 @@ "ServiceStatus", ">" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -46970,7 +47028,7 @@ "ServiceStatus", ">) => void" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -46987,7 +47045,7 @@ "ServiceStatus", ">" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -47010,7 +47068,7 @@ "ServiceStatus", ">>" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -47029,7 +47087,7 @@ "ServiceStatus", ">" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false }, @@ -47045,7 +47103,7 @@ "signature": [ "() => boolean" ], - "path": "src/core/server/status/types.ts", + "path": "node_modules/@types/kbn__core-status-server/index.d.ts", "deprecated": false, "trackAdoption": false, "children": [], @@ -52214,7 +52272,7 @@ "signature": [ "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -52405,7 +52463,7 @@ "signature": [ "{ readonly available: Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }>; readonly degraded: Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }>; readonly unavailable: Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }>; readonly critical: Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>; }" ], - "path": "node_modules/@types/kbn__core-base-common/index.d.ts", + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 1bd545035359a8..8493bbeb60153f 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) for que | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2657 | 1 | 61 | 2 | +| 2657 | 1 | 58 | 2 | ## Client diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index daf36243e408dd..a9828ba77768c1 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index d7da06c8bda6e6..ed6401ee90e45b 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 7e58cc9e1a86a4..57403c81c804f6 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index f7f878ec5cf745..3fdc8ef0dce571 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 5206f1ec467308..05ce7913fdb1f4 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 948da55a39f746..0bd7f60c7859d1 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 95fa4182594f84..d31af9be4e4a72 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 19de55351a8de5..e9b13996dac8cc 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index b1851139b7d9e3..8bc524181fa7fb 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 892d584ba199e2..a222c1751a304e 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 2dd8caad2c6552..ae2db4b7642391 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index df2ac0366eadfe..aae826f6eabd0c 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -74,7 +74,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | savedObjectsTaggingOss, dashboard | 8.8.0 | | | dashboard | 8.8.0 | | | maps, dashboard, @kbn/core-saved-objects-migration-server-internal | 8.8.0 | -| | monitoring, kibanaUsageCollection, @kbn/core-metrics-server-internal, @kbn/core-usage-data-server-internal | 8.8.0 | +| | monitoring, kibanaUsageCollection, @kbn/core-metrics-server-internal, @kbn/core-status-server-internal, @kbn/core-usage-data-server-internal | 8.8.0 | | | security, fleet | 8.8.0 | | | security, fleet | 8.8.0 | | | security, fleet | 8.8.0 | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 600739e4a9fdee..ccddf195d99cd4 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -70,6 +70,14 @@ so TS and code-reference navigation might not highlight them. | +## @kbn/core-status-server-internal + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [status.ts](https://github.com/elastic/kibana/tree/main/packages/core/status/core-status-server-internal/src/routes/status.ts#:~:text=process), [status.ts](https://github.com/elastic/kibana/tree/main/packages/core/status/core-status-server-internal/src/routes/status.ts#:~:text=process) | 8.8.0 | + + + ## @kbn/core-usage-data-server-internal | Deprecated API | Reference location(s) | Remove By | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 8545316f77c0fe..2ca551b49fc6c0 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -80,7 +80,7 @@ so TS and code-reference navigation might not highlight them. | Note to maintainers: when looking at usages, mind that typical use could be inside a `catch` block, so TS and code-reference navigation might not highlight them. | | @kbn/core-saved-objects-migration-server-internal | | [document_migrator.test.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.test.ts#:~:text=warning), [migration_logger.ts](https://github.com/elastic/kibana/tree/main/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/migration_logger.ts#:~:text=warning) | 8.8.0 | -| @kbn/core-metrics-server-internal | | [ops_metrics_collector.ts](https://github.com/elastic/kibana/tree/main/packages/core/metrics/core-metrics-server-internal/src/ops_metrics_collector.ts#:~:text=process), [get_ops_metrics_log.ts](https://github.com/elastic/kibana/tree/main/packages/core/metrics/core-metrics-server-internal/src/logging/get_ops_metrics_log.ts#:~:text=process), [get_ops_metrics_log.test.ts](https://github.com/elastic/kibana/tree/main/packages/core/metrics/core-metrics-server-internal/src/logging/get_ops_metrics_log.test.ts#:~:text=process), [core_usage_data_service.ts](https://github.com/elastic/kibana/tree/main/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_data_service.ts#:~:text=process), [core_usage_data_service.ts](https://github.com/elastic/kibana/tree/main/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_data_service.ts#:~:text=process), [core_usage_data_service.ts](https://github.com/elastic/kibana/tree/main/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_data_service.ts#:~:text=process) | 8.8.0 | +| @kbn/core-metrics-server-internal | | [ops_metrics_collector.ts](https://github.com/elastic/kibana/tree/main/packages/core/metrics/core-metrics-server-internal/src/ops_metrics_collector.ts#:~:text=process), [get_ops_metrics_log.ts](https://github.com/elastic/kibana/tree/main/packages/core/metrics/core-metrics-server-internal/src/logging/get_ops_metrics_log.ts#:~:text=process), [get_ops_metrics_log.test.ts](https://github.com/elastic/kibana/tree/main/packages/core/metrics/core-metrics-server-internal/src/logging/get_ops_metrics_log.test.ts#:~:text=process), [status.ts](https://github.com/elastic/kibana/tree/main/packages/core/status/core-status-server-internal/src/routes/status.ts#:~:text=process), [status.ts](https://github.com/elastic/kibana/tree/main/packages/core/status/core-status-server-internal/src/routes/status.ts#:~:text=process), [core_usage_data_service.ts](https://github.com/elastic/kibana/tree/main/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_data_service.ts#:~:text=process), [core_usage_data_service.ts](https://github.com/elastic/kibana/tree/main/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_data_service.ts#:~:text=process), [core_usage_data_service.ts](https://github.com/elastic/kibana/tree/main/packages/core/usage-data/core-usage-data-server-internal/src/core_usage_data_service.ts#:~:text=process) | 8.8.0 | diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 334a2c08e23c39..090051819ee525 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 6eb89f79f48077..6201c3124a2333 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 3ddbd42c2bc732..d6f701b24d111e 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 362609d3d6d49c..81db63354eed8b 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 58bb7cbddd42b5..e8be99273583db 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 002dd9eb271396..1f9272fc71406a 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 5a45b7486d4c96..520fe453576b44 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index b3f3fc87bda00d..890f44f48dfcca 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 0161dd80da0d72..41817a2babd3f2 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.devdocs.json b/api_docs/event_log.devdocs.json index 8e717efd4ad23c..491bb3f1654233 100644 --- a/api_docs/event_log.devdocs.json +++ b/api_docs/event_log.devdocs.json @@ -696,6 +696,48 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "eventLog", + "id": "def-server.ClusterClientAdapter.aggregateEventsWithAuthFilter", + "type": "Function", + "tags": [], + "label": "aggregateEventsWithAuthFilter", + "description": [], + "signature": [ + "(queryOptions: ", + "AggregateEventsWithAuthFilter", + ") => Promise<", + { + "pluginId": "eventLog", + "scope": "server", + "docId": "kibEventLogPluginApi", + "section": "def-server.AggregateEventsBySavedObjectResult", + "text": "AggregateEventsBySavedObjectResult" + }, + ">" + ], + "path": "x-pack/plugins/event_log/server/es/cluster_client_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "eventLog", + "id": "def-server.ClusterClientAdapter.aggregateEventsWithAuthFilter.$1", + "type": "Object", + "tags": [], + "label": "queryOptions", + "description": [], + "signature": [ + "AggregateEventsWithAuthFilter" + ], + "path": "x-pack/plugins/event_log/server/es/cluster_client_adapter.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -1007,6 +1049,82 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "eventLog", + "id": "def-server.IEventLogClient.aggregateEventsWithAuthFilter", + "type": "Function", + "tags": [], + "label": "aggregateEventsWithAuthFilter", + "description": [], + "signature": [ + "(type: string, authFilter: ", + "KueryNode", + ", options?: Partial<", + "AggregateOptionsType", + "> | undefined) => Promise<", + { + "pluginId": "eventLog", + "scope": "server", + "docId": "kibEventLogPluginApi", + "section": "def-server.AggregateEventsBySavedObjectResult", + "text": "AggregateEventsBySavedObjectResult" + }, + ">" + ], + "path": "x-pack/plugins/event_log/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "eventLog", + "id": "def-server.IEventLogClient.aggregateEventsWithAuthFilter.$1", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/event_log/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "eventLog", + "id": "def-server.IEventLogClient.aggregateEventsWithAuthFilter.$2", + "type": "Object", + "tags": [], + "label": "authFilter", + "description": [], + "signature": [ + "KueryNode" + ], + "path": "x-pack/plugins/event_log/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "eventLog", + "id": "def-server.IEventLogClient.aggregateEventsWithAuthFilter.$3", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "Partial<", + "AggregateOptionsType", + "> | undefined" + ], + "path": "x-pack/plugins/event_log/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 3867ef968cdda5..af0b5490c3e3e0 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 100 | 0 | 100 | 9 | +| 106 | 0 | 106 | 10 | ## Server diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index f8a6757785b98f..3e0211b9f284c6 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 9c151c832439fe..4794e6477d61b0 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 18e588eda03225..8ce939920ce5c0 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 7c7fcf1e51a85e..491323f11e1c61 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 227caffdd86aef..c4a81fbce92559 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 73127734fb39d0..00cdc709d7d433 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index ee91044586ad45..7ce33c3dc83513 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 30188432c4589b..e3f630ad08eada 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index abbd5e0f52ab51..65dcbadeb689b5 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index ae05b346c5294f..680c7be5ac3b48 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 3df0f71990ee19..61096294f663a3 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 312da9ec73cca8..b59a856511bd1e 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 9720c8b749c920..7b984b1b3ced18 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 3bc004877bf6d4..c5db0bef7dc547 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index d3bfbec1eafaa5..ad7f8812cd8b86 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 47ac9e94ccb6fe..864e17ba18d7f5 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 00ef1834df39bb..b9f59064095fd1 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index b94441baeff075..2a3701b79c6d76 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 212a823589def5..c444592ed14ab7 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 151db33c2bbd07..838b35681ace20 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 0633e4a8248504..b81ea75cfaaf8d 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 7cd6a257eeca1a..dcda22c9b4e00e 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index b83bcf59070e4a..a7983f72580bcb 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 05616b0cfadc4e..09d0183b9151d1 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 8454800519cb03..4a00d6265c95d4 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 100b024c58ddf9..5edde61b03b304 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 4606d800cf22e9..c6419c2f9a0db5 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 765ff1f91971fd..4c04ff932864d3 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 4b51bc25be8909..d846738129acd2 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index d5a04ff5eee17e..aad3ebee739701 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index a99efc95e8c132..5239dceb0b4b15 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 1fd92e71b327ac..3549300cebec0a 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 4f9fac4a0b2ece..f31e192ad5409b 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index ada937d1aa30eb..6dcf2355e33221 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 360208b56403ba..3abb48ffa29f94 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 995d23de7fcc71..596bbea03e8a70 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 41246db0a67567..b29cb6fc67bf47 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 82c57310848d5d..f667c806918400 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 3b8859bf24577a..2429ab10684b29 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index a84beaaf76f9c7..b09e1e8ec196f1 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index f81ea7eb893f4c..c993682371dd1e 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index f136b1b4b9722e..34ab9ce22db435 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 4fac55f5f28f2f..a656c6f017a596 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 9a986e49442eb8..62069d98c55501 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index ad805a672ec6af..4086bede91f505 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index d48d41a5c86497..8bfb510cb4fa18 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 1e6fbb0c526198..5a928943d1e94d 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 4ed5acbd873d26..d5e32b85b786fe 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 1a85935c87425d..84f3f19cf92ece 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index ac39a7961593a8..457bb48fbcdc19 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index fc5cd3bfb84380..0afa1ba8252404 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 4c9c75e8523909..baad9a7e2452dd 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 92c14242978161..3e71f0cc873c78 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index da3c85dc76a4e6..1d1dafb69871bf 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index e291353f701f69..31d93967d234db 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index e1d48305d2290f..06c0a6252f8605 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 1b208d9a634874..167b9518fbfdd5 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 3ad4f503057fac..027dc4ea5eb7b5 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 4779f2f4f68b53..b3a70181b0c2d0 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 701892c07d6fb6..f96bd7d5c5e6ea 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.devdocs.json b/api_docs/kbn_core_base_common.devdocs.json index 5a164327bf3384..e5fae7dc02d767 100644 --- a/api_docs/kbn_core_base_common.devdocs.json +++ b/api_docs/kbn_core_base_common.devdocs.json @@ -142,109 +142,6 @@ } ], "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatus", - "type": "Interface", - "tags": [], - "label": "ServiceStatus", - "description": [ - "\nThe current status of a service at a point in time.\n" - ], - "signature": [ - { - "pluginId": "@kbn/core-base-common", - "scope": "server", - "docId": "kibKbnCoreBaseCommonPluginApi", - "section": "def-server.ServiceStatus", - "text": "ServiceStatus" - }, - "" - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatus.level", - "type": "CompoundType", - "tags": [], - "label": "level", - "description": [ - "\nThe current availability level of the service." - ], - "signature": [ - "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatus.summary", - "type": "string", - "tags": [], - "label": "summary", - "description": [ - "\nA high-level summary of the service status." - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatus.detail", - "type": "string", - "tags": [], - "label": "detail", - "description": [ - "\nA more detailed description of the service status." - ], - "signature": [ - "string | undefined" - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatus.documentationUrl", - "type": "string", - "tags": [], - "label": "documentationUrl", - "description": [ - "\nA URL to open in a new tab about how to resolve or troubleshoot the problem." - ], - "signature": [ - "string | undefined" - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatus.meta", - "type": "Uncategorized", - "tags": [], - "label": "meta", - "description": [ - "\nAny JSON-serializable data to be included in the HTTP API response. Useful for providing more fine-grained,\nmachine-readable information about the service status. May include status information for underlying features." - ], - "signature": [ - "Meta | undefined" - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false } ], "enums": [ @@ -308,44 +205,9 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false - }, - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatusLevel", - "type": "Type", - "tags": [], - "label": "ServiceStatusLevel", - "description": [ - "\nA convenience type that represents the union of each value in {@link ServiceStatusLevels}." - ], - "signature": [ - "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false } ], - "objects": [ - { - "parentPluginId": "@kbn/core-base-common", - "id": "def-server.ServiceStatusLevels", - "type": "Object", - "tags": [], - "label": "ServiceStatusLevels", - "description": [ - "\nThe current \"level\" of availability of a service.\n" - ], - "signature": [ - "{ readonly available: Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }>; readonly degraded: Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }>; readonly unavailable: Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }>; readonly critical: Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>; }" - ], - "path": "packages/core/base/core-base-common/src/service_status.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ] + "objects": [] }, "common": { "classes": [], diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 6f65974f3df957..368a5dd0008cac 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; @@ -21,13 +21,10 @@ Contact Kibana Core for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 20 | 0 | 3 | 0 | +| 12 | 0 | 3 | 0 | ## Server -### Objects - - ### Interfaces diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 3ac31dbf66d235..6d155ce49d85ea 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 5d9da0822c070a..66f5f7450be48b 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 0fb84b17ee969d..3ce0e791b74649 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 24dc0372c51ec7..7c6f27244f0d7a 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index a52d64e5e6e200..3849e728af3e27 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index 5e2bfe3318f47c..91a0837f38318e 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 8e3c4efe990f0d..724e892be1c60b 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index ecc9bc1bad7b3b..25d6e2dae632f9 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index fa73a6310dd904..5727d5efa48df1 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index e9d543f5eab88e..39ec5296fe70ec 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 5e380c589df455..74e947bc8463da 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 86d55e1e9c44d1..e91fb82f806103 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 6dd116c3c46f26..70564fe13edbbb 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 96418b9c64b682..91f7162c82f7ed 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index b557d4e5c473ab..8073bb4836752f 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index 0cacd094cfbb99..5678298ca733c3 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 2c72b3d00c5990..96f7ecec3bc42d 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 1582e2b3c6a478..824030f1daa252 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 7cad22cf1928bb..db5d060f35a8d8 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index ac6c785eb5bbc8..1780ab586e6490 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 65546108902bde..11ccbdd98c2f3b 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index b119bfb2ad808a..c698d02940bcf9 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index d8d8afa63313df..0c8b555c777211 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 7bb38a3c5f0bf3..92e416c29bf95b 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index da30359337d2fc..37c2becd7354ba 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 115eabde42da7c..390a061c8981c5 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index edfcddc56edc18..b42023a54f6152 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 6d3b3e2cf0095e..9ab334b2c6624f 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index fcc2284968ba8b..8787f12bceadfc 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 48919a14adc5da..95ff1d8689a573 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 0a87811f9fa6d1..aea2f328723ab5 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index be640b0bd6c12f..f3764fe8d6f943 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 4d9363ee6d0670..3a1182ada50652 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 8e1632be18c1bc..a4cc0208bd03f9 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 7fee5984f817aa..a4d41b900aef82 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index c989c3c38eff42..c638049a6b3e03 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index ab44b913d6d22f..ea182d13d4240c 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index a23bfab2355724..db770a72f35975 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index cc4ba299fcd2f8..264b5b1a331667 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index f3ad4235ca0bdd..1403f95b83599b 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 8e036459534723..f387d4a897882f 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index cd7e2beebf898a..96020064f61fb8 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 355ed41119b58b..1315293ec65a2c 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index bca3d59fc66ba0..e1f3750c84a27e 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 8c1ce95e5da381..53e3dbb94f3604 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 9855a467f8ff3a..9af745103bea09 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index e10bab2bb0ef1d..b8f73ee93016a0 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 6bbcf9a1ed58f1..89a06be37a6fa8 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index ca0b28fad3b83b..a396a416f9d749 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index d0b3e5f8750ae1..7140c88921d6f7 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index 09595678ffd95d..2164762ea7a020 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index f98bc4b4caa51a..828f4f1a12d5f0 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 2d6f60b30b0f4b..c836a584e00952 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 7d6d538a4a3453..daf159516318b3 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 965b44c3d7f494..b19ffe7e38b18d 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index baf526633cb7fa..cd01fd52739292 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index c7e3e793271dc5..150968cb0570e9 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index ba256a3dc7685e..788e4f701670f8 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 20ddad2be7f374..8101e973753e8f 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 6278558d4a15bd..94799690c450d7 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 774dbb4aa58f22..7a3515639112ec 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index b68f29089b3c5e..c2a89783ff2339 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 9da56c2b13d540..3635d788ab55c0 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index fc5ad5407ea58e..9e3162a0eee92f 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index cbc248a380a6eb..4c2b69880d9b78 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 6c389f91fb1dee..b89677d1be7437 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index e8223e2b459771..742de4384ddd0e 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 2c27b78aff6bb7..8621952d15a633 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 197b80b4ba6304..518d5c12f5d68b 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index bf9b1d6b28607d..6210a65c921594 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 21561dfeb133d9..2f7ec5fe4f2e06 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index d4790272c355d5..e9a8d04e8c4629 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 1e44984b977aef..0cb0033765ac1c 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 064c1a7409c91d..08c1e192449f67 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 68d8ba8c77e35a..c1665898b331dd 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 33c45bca370dbd..50fa0b1303d191 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 8fb776cf682400..01133a602b6168 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 37b831645698d9..63a4b1b1afc781 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index b1e0f26591dea8..0052df5199754d 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 76e68572653434..fb4b4c5e400251 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index b0656d2d7698c9..0c7b97f3d40aa1 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index ecd8eb6b89e587..8a0f130084dcc2 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 3095a10b0e8a37..57a308d4daba91 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 6e6235f54d936e..0585dfbd2b21a5 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 9ba194c06f4bd5..20980722e5e605 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 841d63be63be47..0f69c3872f40b7 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index 62ca0892a8ef0f..b67d4011f24c57 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 6db912ca3d51da..1444f1dc2bebab 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 124ba03f2d7cb0..a20cf1a5fb3b9a 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index 436795ec64440f..c5399214f2edff 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index d39b682d0e9227..3560b5d875cc38 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 097b612967b60f..60d095cdc08424 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 5cfc809e628d45..8c065c5e187c64 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 0735565b60ba30..e48205627b9089 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.devdocs.json b/api_docs/kbn_core_status_common.devdocs.json new file mode 100644 index 00000000000000..b49607b86963e8 --- /dev/null +++ b/api_docs/kbn_core_status_common.devdocs.json @@ -0,0 +1,242 @@ +{ + "id": "@kbn/core-status-common", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.CoreStatus", + "type": "Interface", + "tags": [], + "label": "CoreStatus", + "description": [ + "\nStatus of core services.\n" + ], + "path": "packages/core/status/core-status-common/src/core_status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.CoreStatus.elasticsearch", + "type": "Object", + "tags": [], + "label": "elasticsearch", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-common", + "scope": "common", + "docId": "kibKbnCoreStatusCommonPluginApi", + "section": "def-common.ServiceStatus", + "text": "ServiceStatus" + }, + "" + ], + "path": "packages/core/status/core-status-common/src/core_status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.CoreStatus.savedObjects", + "type": "Object", + "tags": [], + "label": "savedObjects", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-common", + "scope": "common", + "docId": "kibKbnCoreStatusCommonPluginApi", + "section": "def-common.ServiceStatus", + "text": "ServiceStatus" + }, + "" + ], + "path": "packages/core/status/core-status-common/src/core_status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatus", + "type": "Interface", + "tags": [], + "label": "ServiceStatus", + "description": [ + "\nThe current status of a service at a point in time.\n" + ], + "signature": [ + { + "pluginId": "@kbn/core-status-common", + "scope": "common", + "docId": "kibKbnCoreStatusCommonPluginApi", + "section": "def-common.ServiceStatus", + "text": "ServiceStatus" + }, + "" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatus.level", + "type": "CompoundType", + "tags": [], + "label": "level", + "description": [ + "\nThe current availability level of the service." + ], + "signature": [ + "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatus.summary", + "type": "string", + "tags": [], + "label": "summary", + "description": [ + "\nA high-level summary of the service status." + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatus.detail", + "type": "string", + "tags": [], + "label": "detail", + "description": [ + "\nA more detailed description of the service status." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatus.documentationUrl", + "type": "string", + "tags": [], + "label": "documentationUrl", + "description": [ + "\nA URL to open in a new tab about how to resolve or troubleshoot the problem." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatus.meta", + "type": "Uncategorized", + "tags": [], + "label": "meta", + "description": [ + "\nAny JSON-serializable data to be included in the HTTP API response. Useful for providing more fine-grained,\nmachine-readable information about the service status. May include status information for underlying features." + ], + "signature": [ + "Meta | undefined" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatusLevel", + "type": "Type", + "tags": [], + "label": "ServiceStatusLevel", + "description": [ + "\nA convenience type that represents the union of each value in {@link ServiceStatusLevels}." + ], + "signature": [ + "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatusLevelId", + "type": "Type", + "tags": [], + "label": "ServiceStatusLevelId", + "description": [ + "\nPossible values for the ID of a {@link ServiceStatusLevel}\n" + ], + "signature": [ + "\"critical\" | \"degraded\" | \"unavailable\" | \"available\"" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/core-status-common", + "id": "def-common.ServiceStatusLevels", + "type": "Object", + "tags": [], + "label": "ServiceStatusLevels", + "description": [ + "\nThe current \"level\" of availability of a service.\n" + ], + "signature": [ + "{ readonly available: Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }>; readonly degraded: Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }>; readonly unavailable: Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }>; readonly critical: Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>; }" + ], + "path": "packages/core/status/core-status-common/src/service_status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx new file mode 100644 index 00000000000000..bde6925ddfcf2d --- /dev/null +++ b/api_docs/kbn_core_status_common.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnCoreStatusCommonPluginApi +slug: /kibana-dev-docs/api/kbn-core-status-common +title: "@kbn/core-status-common" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/core-status-common plugin +date: 2022-09-10 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] +--- +import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; + + + +Contact Kibana Core for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 12 | 0 | 2 | 0 | + +## Common + +### Objects + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_status_common_internal.devdocs.json b/api_docs/kbn_core_status_common_internal.devdocs.json new file mode 100644 index 00000000000000..39b4d63b9e25a9 --- /dev/null +++ b/api_docs/kbn_core_status_common_internal.devdocs.json @@ -0,0 +1,355 @@ +{ + "id": "@kbn/core-status-common-internal", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.ServerVersion", + "type": "Interface", + "tags": [], + "label": "ServerVersion", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.ServerVersion.number", + "type": "string", + "tags": [], + "label": "number", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.ServerVersion.build_hash", + "type": "string", + "tags": [], + "label": "build_hash", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.ServerVersion.build_number", + "type": "number", + "tags": [], + "label": "build_number", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.ServerVersion.build_snapshot", + "type": "boolean", + "tags": [], + "label": "build_snapshot", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusInfo", + "type": "Interface", + "tags": [], + "label": "StatusInfo", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusInfo.overall", + "type": "Object", + "tags": [], + "label": "overall", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfoServiceStatus", + "text": "StatusInfoServiceStatus" + } + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusInfo.core", + "type": "Object", + "tags": [], + "label": "core", + "description": [], + "signature": [ + "{ elasticsearch: ", + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfoServiceStatus", + "text": "StatusInfoServiceStatus" + }, + "; savedObjects: ", + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfoServiceStatus", + "text": "StatusInfoServiceStatus" + }, + "; }" + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusInfo.plugins", + "type": "Object", + "tags": [], + "label": "plugins", + "description": [], + "signature": [ + "{ [x: string]: ", + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfoServiceStatus", + "text": "StatusInfoServiceStatus" + }, + "; }" + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusInfoServiceStatus", + "type": "Interface", + "tags": [], + "label": "StatusInfoServiceStatus", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfoServiceStatus", + "text": "StatusInfoServiceStatus" + }, + " extends Omit<", + "ServiceStatus", + ", \"level\">" + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusInfoServiceStatus.level", + "type": "CompoundType", + "tags": [], + "label": "level", + "description": [], + "signature": [ + "\"critical\" | \"degraded\" | \"unavailable\" | \"available\"" + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusResponse", + "type": "Interface", + "tags": [], + "label": "StatusResponse", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusResponse.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusResponse.uuid", + "type": "string", + "tags": [], + "label": "uuid", + "description": [], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusResponse.version", + "type": "Object", + "tags": [], + "label": "version", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.ServerVersion", + "text": "ServerVersion" + } + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusResponse.status", + "type": "Object", + "tags": [], + "label": "status", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfo", + "text": "StatusInfo" + } + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusResponse.metrics", + "type": "CompoundType", + "tags": [], + "label": "metrics", + "description": [], + "signature": [ + "Omit<", + "OpsMetrics", + ", \"collected_at\"> & { last_updated: string; collection_interval_in_millis: number; requests: { status_codes: Record; }; }" + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.ServerMetrics", + "type": "Type", + "tags": [], + "label": "ServerMetrics", + "description": [], + "signature": [ + "Omit<", + "OpsMetrics", + ", \"collected_at\"> & { last_updated: string; collection_interval_in_millis: number; requests: { status_codes: Record; }; }" + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-common-internal", + "id": "def-common.StatusInfoCoreStatus", + "type": "Type", + "tags": [], + "label": "StatusInfoCoreStatus", + "description": [ + "\nCopy all the services listed in CoreStatus with their specific ServiceStatus declarations\nbut overwriting the `level` to its stringified version." + ], + "signature": [ + "{ elasticsearch: ", + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfoServiceStatus", + "text": "StatusInfoServiceStatus" + }, + "; savedObjects: ", + { + "pluginId": "@kbn/core-status-common-internal", + "scope": "common", + "docId": "kibKbnCoreStatusCommonInternalPluginApi", + "section": "def-common.StatusInfoServiceStatus", + "text": "StatusInfoServiceStatus" + }, + "; }" + ], + "path": "packages/core/status/core-status-common-internal/src/status.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx new file mode 100644 index 00000000000000..f8b8988e0f703e --- /dev/null +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnCoreStatusCommonInternalPluginApi +slug: /kibana-dev-docs/api/kbn-core-status-common-internal +title: "@kbn/core-status-common-internal" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/core-status-common-internal plugin +date: 2022-09-10 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] +--- +import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; + + + +Contact Kibana Core for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 19 | 0 | 18 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_status_server.devdocs.json b/api_docs/kbn_core_status_server.devdocs.json new file mode 100644 index 00000000000000..6438e27aa69d3f --- /dev/null +++ b/api_docs/kbn_core_status_server.devdocs.json @@ -0,0 +1,378 @@ +{ + "id": "@kbn/core-status-server", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.CoreStatus", + "type": "Interface", + "tags": [], + "label": "CoreStatus", + "description": [ + "\nStatus of core services.\n" + ], + "signature": [ + "CoreStatus" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.CoreStatus.elasticsearch", + "type": "Object", + "tags": [], + "label": "elasticsearch", + "description": [], + "signature": [ + "ServiceStatus", + "" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.CoreStatus.savedObjects", + "type": "Object", + "tags": [], + "label": "savedObjects", + "description": [], + "signature": [ + "ServiceStatus", + "" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatus", + "type": "Interface", + "tags": [], + "label": "ServiceStatus", + "description": [ + "\nThe current status of a service at a point in time.\n" + ], + "signature": [ + "ServiceStatus", + "" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatus.level", + "type": "CompoundType", + "tags": [], + "label": "level", + "description": [ + "\nThe current availability level of the service." + ], + "signature": [ + "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatus.summary", + "type": "string", + "tags": [], + "label": "summary", + "description": [ + "\nA high-level summary of the service status." + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatus.detail", + "type": "string", + "tags": [], + "label": "detail", + "description": [ + "\nA more detailed description of the service status." + ], + "signature": [ + "string | undefined" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatus.documentationUrl", + "type": "string", + "tags": [], + "label": "documentationUrl", + "description": [ + "\nA URL to open in a new tab about how to resolve or troubleshoot the problem." + ], + "signature": [ + "string | undefined" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatus.meta", + "type": "Uncategorized", + "tags": [], + "label": "meta", + "description": [ + "\nAny JSON-serializable data to be included in the HTTP API response. Useful for providing more fine-grained,\nmachine-readable information about the service status. May include status information for underlying features." + ], + "signature": [ + "Meta | undefined" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup", + "type": "Interface", + "tags": [], + "label": "StatusServiceSetup", + "description": [ + "\nAPI for accessing status of Core and this plugin's dependencies as well as for customizing this plugin's status.\n" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup.core$", + "type": "Object", + "tags": [], + "label": "core$", + "description": [ + "\nCurrent status for all Core services." + ], + "signature": [ + "Observable", + "<", + "CoreStatus", + ">" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup.overall$", + "type": "Object", + "tags": [], + "label": "overall$", + "description": [ + "\nOverall system status for all of Kibana.\n" + ], + "signature": [ + "Observable", + "<", + "ServiceStatus", + ">" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup.set", + "type": "Function", + "tags": [], + "label": "set", + "description": [ + "\nAllows a plugin to specify a custom status dependent on its own criteria.\nCompletely overrides the default inherited status.\n" + ], + "signature": [ + "(status$: ", + "Observable", + "<", + "ServiceStatus", + ">) => void" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup.set.$1", + "type": "Object", + "tags": [], + "label": "status$", + "description": [], + "signature": [ + "Observable", + "<", + "ServiceStatus", + ">" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup.dependencies$", + "type": "Object", + "tags": [], + "label": "dependencies$", + "description": [ + "\nCurrent status for all plugins this plugin depends on.\nEach key of the `Record` is a plugin id." + ], + "signature": [ + "Observable", + ">>" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup.derivedStatus$", + "type": "Object", + "tags": [], + "label": "derivedStatus$", + "description": [ + "\nThe status of this plugin as derived from its dependencies.\n" + ], + "signature": [ + "Observable", + "<", + "ServiceStatus", + ">" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.StatusServiceSetup.isStatusPageAnonymous", + "type": "Function", + "tags": [], + "label": "isStatusPageAnonymous", + "description": [ + "\nWhether or not the status HTTP APIs are available to unauthenticated users when an authentication provider is\npresent." + ], + "signature": [ + "() => boolean" + ], + "path": "packages/core/status/core-status-server/src/contracts.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatusLevel", + "type": "Type", + "tags": [], + "label": "ServiceStatusLevel", + "description": [ + "\nA convenience type that represents the union of each value in {@link ServiceStatusLevels}." + ], + "signature": [ + "Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }> | Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }> | Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }> | Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatusLevelId", + "type": "Type", + "tags": [], + "label": "ServiceStatusLevelId", + "description": [ + "\nPossible values for the ID of a {@link ServiceStatusLevel}\n" + ], + "signature": [ + "\"critical\" | \"degraded\" | \"unavailable\" | \"available\"" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/core-status-server", + "id": "def-server.ServiceStatusLevels", + "type": "Object", + "tags": [], + "label": "ServiceStatusLevels", + "description": [ + "\nThe current \"level\" of availability of a service.\n" + ], + "signature": [ + "{ readonly available: Readonly<{ toString: () => \"available\"; valueOf: () => 0; toJSON: () => \"available\"; }>; readonly degraded: Readonly<{ toString: () => \"degraded\"; valueOf: () => 1; toJSON: () => \"degraded\"; }>; readonly unavailable: Readonly<{ toString: () => \"unavailable\"; valueOf: () => 2; toJSON: () => \"unavailable\"; }>; readonly critical: Readonly<{ toString: () => \"critical\"; valueOf: () => 3; toJSON: () => \"critical\"; }>; }" + ], + "path": "node_modules/@types/kbn__core-status-common/index.d.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx new file mode 100644 index 00000000000000..92b56d4cc62fe8 --- /dev/null +++ b/api_docs/kbn_core_status_server.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnCoreStatusServerPluginApi +slug: /kibana-dev-docs/api/kbn-core-status-server +title: "@kbn/core-status-server" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/core-status-server plugin +date: 2022-09-10 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] +--- +import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; + + + +Contact Kibana Core for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 20 | 0 | 1 | 0 | + +## Server + +### Objects + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_status_server_internal.devdocs.json b/api_docs/kbn_core_status_server_internal.devdocs.json new file mode 100644 index 00000000000000..d24cd2e1438309 --- /dev/null +++ b/api_docs/kbn_core_status_server_internal.devdocs.json @@ -0,0 +1,440 @@ +{ + "id": "@kbn/core-status-server-internal", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusService", + "type": "Class", + "tags": [], + "label": "StatusService", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-server-internal", + "scope": "server", + "docId": "kibKbnCoreStatusServerInternalPluginApi", + "section": "def-server.StatusService", + "text": "StatusService" + }, + " implements ", + "CoreService", + "<", + "InternalStatusServiceSetup", + ", void>" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusService.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusService.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "coreContext", + "description": [], + "signature": [ + "CoreContext" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusService.setup", + "type": "Function", + "tags": [], + "label": "setup", + "description": [], + "signature": [ + "({ analytics, elasticsearch, pluginDependencies, http, metrics, savedObjects, environment, coreUsageData, }: ", + { + "pluginId": "@kbn/core-status-server-internal", + "scope": "server", + "docId": "kibKbnCoreStatusServerInternalPluginApi", + "section": "def-server.StatusServiceSetupDeps", + "text": "StatusServiceSetupDeps" + }, + ") => Promise<{ core$: ", + "Observable", + "<", + "CoreStatus", + ">; coreOverall$: ", + "Observable", + "<", + "ServiceStatus", + ">; overall$: ", + "Observable", + "<", + "ServiceStatus", + ">; plugins: { set: (plugin: string, status$: ", + "Observable", + "<", + "ServiceStatus", + ">) => void; getDependenciesStatus$: (plugin: string) => ", + "Observable", + ">>; getDerivedStatus$: (plugin: string) => ", + "Observable", + "<", + "ServiceStatus", + ">; }; isStatusPageAnonymous: () => boolean; }>" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusService.setup.$1", + "type": "Object", + "tags": [], + "label": "{\n analytics,\n elasticsearch,\n pluginDependencies,\n http,\n metrics,\n savedObjects,\n environment,\n coreUsageData,\n }", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-status-server-internal", + "scope": "server", + "docId": "kibKbnCoreStatusServerInternalPluginApi", + "section": "def-server.StatusServiceSetupDeps", + "text": "StatusServiceSetupDeps" + } + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusService.start", + "type": "Function", + "tags": [], + "label": "start", + "description": [], + "signature": [ + "() => void" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusService.stop", + "type": "Function", + "tags": [], + "label": "stop", + "description": [], + "signature": [ + "() => void" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.registerStatusRoute", + "type": "Function", + "tags": [], + "label": "registerStatusRoute", + "description": [], + "signature": [ + "({ router, config, metrics, status, incrementUsageCounter, }: Deps) => void" + ], + "path": "packages/core/status/core-status-server-internal/src/routes/status.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.registerStatusRoute.$1", + "type": "Object", + "tags": [], + "label": "{\n router,\n config,\n metrics,\n status,\n incrementUsageCounter,\n}", + "description": [], + "signature": [ + "Deps" + ], + "path": "packages/core/status/core-status-server-internal/src/routes/status.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps", + "type": "Interface", + "tags": [], + "label": "StatusServiceSetupDeps", + "description": [], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.analytics", + "type": "Object", + "tags": [], + "label": "analytics", + "description": [], + "signature": [ + "{ optIn: (optInConfig: ", + "OptInConfig", + ") => void; reportEvent: (eventType: string, eventData: EventTypeData) => void; readonly telemetryCounter$: ", + "Observable", + "<", + "TelemetryCounter", + ">; registerEventType: (eventTypeOps: ", + "EventTypeOpts", + ") => void; registerShipper: (Shipper: ", + "ShipperClassConstructor", + ", shipperConfig: ShipperConfig, opts?: ", + "RegisterShipperOpts", + " | undefined) => void; registerContextProvider: (contextProviderOpts: ", + "ContextProviderOpts", + ") => void; removeContextProvider: (contextProviderName: string) => void; }" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.elasticsearch", + "type": "Object", + "tags": [], + "label": "elasticsearch", + "description": [], + "signature": [ + "{ status$: ", + "Observable", + "<", + "ServiceStatus", + "<", + "ElasticsearchStatusMeta", + ">>; }" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.environment", + "type": "Object", + "tags": [], + "label": "environment", + "description": [], + "signature": [ + "InternalEnvironmentServicePreboot" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.pluginDependencies", + "type": "Object", + "tags": [], + "label": "pluginDependencies", + "description": [], + "signature": [ + "ReadonlyMap" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.http", + "type": "Object", + "tags": [], + "label": "http", + "description": [], + "signature": [ + "InternalHttpServiceSetup" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.metrics", + "type": "Object", + "tags": [], + "label": "metrics", + "description": [], + "signature": [ + "MetricsServiceSetup" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.savedObjects", + "type": "Object", + "tags": [], + "label": "savedObjects", + "description": [], + "signature": [ + "{ status$: ", + "Observable", + "<", + "ServiceStatus", + "<", + "SavedObjectStatusMeta", + ">>; }" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusServiceSetupDeps.coreUsageData", + "type": "Object", + "tags": [], + "label": "coreUsageData", + "description": [], + "signature": [ + "{ incrementUsageCounter: ", + "CoreIncrementUsageCounter", + "; }" + ], + "path": "packages/core/status/core-status-server-internal/src/status_service.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.StatusConfigType", + "type": "Type", + "tags": [], + "label": "StatusConfigType", + "description": [], + "signature": [ + "{ readonly allowAnonymous: boolean; }" + ], + "path": "packages/core/status/core-status-server-internal/src/status_config.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.statusConfig", + "type": "Object", + "tags": [], + "label": "statusConfig", + "description": [], + "path": "packages/core/status/core-status-server-internal/src/status_config.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.statusConfig.path", + "type": "string", + "tags": [], + "label": "path", + "description": [], + "path": "packages/core/status/core-status-server-internal/src/status_config.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-status-server-internal", + "id": "def-server.statusConfig.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [], + "signature": [ + "ObjectType", + "<{ allowAnonymous: ", + "Type", + "; }>" + ], + "path": "packages/core/status/core-status-server-internal/src/status_config.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx new file mode 100644 index 00000000000000..2d6ea32e7361d8 --- /dev/null +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -0,0 +1,42 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnCoreStatusServerInternalPluginApi +slug: /kibana-dev-docs/api/kbn-core-status-server-internal +title: "@kbn/core-status-server-internal" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/core-status-server-internal plugin +date: 2022-09-10 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] +--- +import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; + + + +Contact Kibana Core for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 22 | 0 | 22 | 1 | + +## Server + +### Objects + + +### Functions + + +### Classes + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_core_status_server_mocks.devdocs.json b/api_docs/kbn_core_status_server_mocks.devdocs.json new file mode 100644 index 00000000000000..85f331d9e7e27c --- /dev/null +++ b/api_docs/kbn_core_status_server_mocks.devdocs.json @@ -0,0 +1,94 @@ +{ + "id": "@kbn/core-status-server-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [ + { + "parentPluginId": "@kbn/core-status-server-mocks", + "id": "def-server.statusServiceMock", + "type": "Object", + "tags": [], + "label": "statusServiceMock", + "description": [], + "path": "packages/core/status/core-status-server-mocks/src/status_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-status-server-mocks", + "id": "def-server.statusServiceMock.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "() => jest.Mocked" + ], + "path": "packages/core/status/core-status-server-mocks/src/status_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-status-server-mocks", + "id": "def-server.statusServiceMock.createSetupContract", + "type": "Function", + "tags": [], + "label": "createSetupContract", + "description": [], + "signature": [ + "() => jest.Mocked<", + "StatusServiceSetup", + ">" + ], + "path": "packages/core/status/core-status-server-mocks/src/status_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + }, + { + "parentPluginId": "@kbn/core-status-server-mocks", + "id": "def-server.statusServiceMock.createInternalSetupContract", + "type": "Function", + "tags": [], + "label": "createInternalSetupContract", + "description": [], + "signature": [ + "() => jest.Mocked<", + "InternalStatusServiceSetup", + ">" + ], + "path": "packages/core/status/core-status-server-mocks/src/status_service.mock.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [] + } + ], + "initialIsOpen": false + } + ] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx new file mode 100644 index 00000000000000..bdfe6900db761d --- /dev/null +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -0,0 +1,30 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnCoreStatusServerMocksPluginApi +slug: /kibana-dev-docs/api/kbn-core-status-server-mocks +title: "@kbn/core-status-server-mocks" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/core-status-server-mocks plugin +date: 2022-09-10 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] +--- +import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; + + + +Contact Kibana Core for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 4 | 0 | 4 | 0 | + +## Server + +### Objects + + diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index bcc58ce97c1720..f21f50e4be1fe9 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index fab15b3ed6f35a..15647342dddb06 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 017403c279a718..36e37f77a6194d 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 4b18d3cb540b5c..fe02ab842adba8 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index d68eda65b74784..ca472346327829 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index d43b64677389ad..a6c20f54519d53 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index a2b638ea5c8f3b..acc89049462fb6 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 6a7ad1ab8e14d6..66cb9a0b33eb02 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 9b16f81a2be4a9..662fd7c508ba71 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 135387c16286c8..8c88455d9b0926 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index cb5b74bd34c0bd..13bab0f2ea1fc1 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 02f152900b4477..5d4a2904c9b548 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 70e8d69a6b17cb..2c449d15974bf3 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 77788c27073dcd..01d0f9a9a6a321 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 669752ea179918..dfea5cf2ab2026 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 653e1b5efe544b..85cc9c38bd3315 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index f7edb115f49a9f..95b42536984fa2 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index f83c97ef5f49d9..e841f9170a1fd0 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 7278c02638113f..f23422a1b253ad 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 044c765674ea12..57fbccecd3fdd6 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index d47c4a94ac5345..d4b4c39f2de253 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 5cc4b3d097f4ff..cbf92ce5c96347 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 5cad59a4b8f74d..ae6572d784a590 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index ca0ada58480340..7a52f9e558bfd4 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 792b606b4133a0..b7944a7d94e9ee 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 6e1eb7f3fcfde7..6040010dd50e45 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 3fa74decb5caac..c9cea912963a81 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index 5c3fcdaab984cb..a129022994df3e 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index ed9435a3b3b748..b578add112d054 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index 3e663271b7a7d4..fa2b54e14253b1 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 89013d791f80d2..a538f4419085b2 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 03c70dae79e772..2d7dfddb7cfde4 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 4f6ed6ee570a8f..78bd769b5616fe 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 0d51ff6ce14658..4555f95d1db3ab 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index dda867b946f49d..f4bb9bdaa32f21 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 1eeda889c5cdd2..305d42d10b555c 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 8c87bc7a914bd1..9ff24d656b6f57 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 1f89b3b7e535a0..c4eced5115fbc1 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 6885069422ac0a..6eee5a2ddc9594 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 771d6d1341fcaf..d449b34a0d001b 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index eb7eb96ae58c22..41fdb074db3083 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index c778ebc86da322..88fdd1d8a30cda 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index f9799e1ac39470..4d281617212ead 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index fc653bed6e7e95..ccd82c4552dab0 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index 12b0ecb60e66ca..c277f36bd68900 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 67f7ef712b4190..b8068d9717b684 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index a8aa07a6cb0ad5..5fad0d1b3c6192 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index cf5344b7847eba..e02e85e387df33 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 59384f2ce9406d..b26e5b25de93b8 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index cb5c6845f2d4f4..236351581f68d4 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 2445802229bf1d..24abda1b0c6e73 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 617d5fec736bf8..e01f3f99ffd81f 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 44df77707e11de..6e2679e6ac26df 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 6917f3fc99b3ba..e7571b2b5f2db5 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 9b30733e7280b3..e31a33e2ae566a 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index d278bd47a83cc6..d96fa6a177e2f4 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index e1c8c47ea5d192..47327f749fc93b 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index d2a1be19c6c177..c6699b94b8a399 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index e4fbf89a1405f1..1820e21e88d48d 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 38f823267cd07d..b5c97c6c0e1985 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index adec0fb8b5efb8..5f500a432f34fa 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index cf020e8b0a27ae..256a6591902899 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 598a866af57e8a..ed97855cf35483 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 7f8c8c61107518..2b84ca3272b691 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 3690bc8cbc2b4c..9f7dcd57ae65a7 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index e30499cbbf39a5..abd918eb8d3985 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 22657a04b1bb90..4a53f6921c66c6 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 19a2c081a5bd76..426a1bbc586abf 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 65f02eb6305e73..17dd013084ddde 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index f84326704b432b..c1a403fe7e707b 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 2553be04e72c4f..be4755193af441 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index e1deb3f5d47f77..7554a6a18493d7 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index e28e8dfe7c35ae..142a54239e5517 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 57ee3c5eaeeac4..1797e343347d88 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 823e9843677a0e..8364ea1f8c53be 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 27455c0dcff207..26110f7aa404d7 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 30e9422c7d0dcc..ffa50fa47a0f7d 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index d382db6b061811..757355b8211db6 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index f719f64919ffe1..726fe4c091d14c 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index 6c98183d2a7ff0..dc28f2e50ce658 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index e96fd6b65b797d..5a0615a5e3b884 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index f082939bf23db8..128001d9f7a5de 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 56d513e6b23953..a491b3eef50b9c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index f2aa470f834cc5..eb074d07ee15bf 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 003b096cfd0f91..7b3a8439e29e08 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 8b61bc3b8fb032..1b151f3099a00b 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 9b0e41366e4922..7690985e6c9f7f 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index 673f7aa80d4184..5c27ce9906bfd6 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index fca609edd1eec1..08f8c0ea2414f2 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index d55f975104ffac..b7b14058fc47e8 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 370bb3fb7b081a..4670ab6757530d 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.devdocs.json b/api_docs/kbn_shared_ux_router.devdocs.json new file mode 100644 index 00000000000000..b3381733e9f8f1 --- /dev/null +++ b/api_docs/kbn_shared_ux_router.devdocs.json @@ -0,0 +1,65 @@ +{ + "id": "@kbn/shared-ux-router", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/shared-ux-router", + "id": "def-common.Route", + "type": "Function", + "tags": [], + "label": "Route", + "description": [ + "\nThis is a wrapper around the react-router-dom Route component that inserts\nMatchPropagator in every application route. It helps track all route changes\nand send them to the execution context, later used to enrich APM\n'route-change' transactions." + ], + "signature": [ + "({ children, component: Component, render, ...rest }: ", + "RouteProps", + ") => JSX.Element" + ], + "path": "packages/shared-ux/router/impl/router.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-router", + "id": "def-common.Route.$1", + "type": "Object", + "tags": [], + "label": "{ children, component: Component, render, ...rest }", + "description": [], + "signature": [ + "RouteProps" + ], + "path": "packages/shared-ux/router/impl/router.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx new file mode 100644 index 00000000000000..90e7d25f00b892 --- /dev/null +++ b/api_docs/kbn_shared_ux_router.mdx @@ -0,0 +1,30 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSharedUxRouterPluginApi +slug: /kibana-dev-docs/api/kbn-shared-ux-router +title: "@kbn/shared-ux-router" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/shared-ux-router plugin +date: 2022-09-10 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] +--- +import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 2 | 0 | 1 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_shared_ux_router_mocks.devdocs.json b/api_docs/kbn_shared_ux_router_mocks.devdocs.json new file mode 100644 index 00000000000000..db66a624416979 --- /dev/null +++ b/api_docs/kbn_shared_ux_router_mocks.devdocs.json @@ -0,0 +1,45 @@ +{ + "id": "@kbn/shared-ux-router-mocks", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/shared-ux-router-mocks", + "id": "def-common.foo", + "type": "Function", + "tags": [], + "label": "foo", + "description": [], + "signature": [ + "() => string" + ], + "path": "packages/shared-ux/router/mocks/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx new file mode 100644 index 00000000000000..5dff7d8731cd4a --- /dev/null +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -0,0 +1,30 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSharedUxRouterMocksPluginApi +slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks +title: "@kbn/shared-ux-router-mocks" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/shared-ux-router-mocks plugin +date: 2022-09-10 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] +--- +import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; + + + +Contact [Owner missing] for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 1 | 0 | 1 | 0 | + +## Common + +### Functions + + diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 9200b11a09b215..aa5ef51758ba33 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index d281f952bbbdfd..194fe83ad1f38a 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index ce6cfca9bcf5c8..5a16ff03fb9901 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index ef9f4272e5ae16..105a4ef0ec531e 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 5e5cd15a358740..71ffb06e4a78f7 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index f09537bfe88aef..05262ee2da8542 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 9bd71879017ce6..99e1dfc8e1cb02 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 9a002696753d01..cf3152a814a0d9 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 5b0eba5853c138..6e824fa356773d 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.devdocs.json b/api_docs/kbn_test.devdocs.json index 3a4cf723d0775e..f36daceb7cab27 100644 --- a/api_docs/kbn_test.devdocs.json +++ b/api_docs/kbn_test.devdocs.json @@ -2669,6 +2669,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "@kbn/test", + "id": "def-server.CreateTestEsClusterOptions.writeLogsToPath", + "type": "string", + "tags": [], + "label": "writeLogsToPath", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "packages/kbn-test/src/es/test_es_cluster.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "@kbn/test", "id": "def-server.CreateTestEsClusterOptions.nodes", diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 2b1cfb4d5c2fe0..aa87ac4e7d9123 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; @@ -21,7 +21,7 @@ Contact Operations for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 253 | 5 | 212 | 11 | +| 254 | 5 | 213 | 11 | ## Server diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 20c4a3eb4f9ba7..9de5f0f3f5929e 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index fb392e818e687e..6285f1eac7ef09 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index c06226b8eba969..6d71d005ef8877 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index b81adb3a56d1d1..93d680eec7468b 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index e75d872f2484db..53fbfddd18b59d 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index b70ee2231fefb1..fa8178a8e940ec 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index b7ddf660ca0df5..32cbe5fc75ada9 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 92cd97760ca7c9..e594effff18d19 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index af84fa702b0759..4d779ad075df5b 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index c6f2cc8482954a..5027bcad2b28b7 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 789133a70ac7ec..a18c550e611328 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 4ea296d9ab1e1a..952430c15e7dd2 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index d69d9e8545c969..934fab6cb77a24 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 169dcb7ee1f23b..3db1b04623d64c 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 7f3978dab8e032..cc1da70e185089 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index a22c71323b68cd..9c97fda0e603cf 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 571dc8691bd0a7..8289ecb41a7b2c 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 201e1c21dffbc6..b2739110c8138c 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index d00e7742b2ed4a..683099eee4fec9 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 751f7ca0cd136b..c66d0b73906be3 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 9a598bdde11fb4..03690c74dc10f8 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index fb06fd880fdb03..b3579c2abc9d06 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index ff860e62ea1b92..3381ec2ec9efca 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index ed642dcfa50a63..b20466ec2a9979 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index ddf5e670048441..1fc969c65cd8cc 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 6fb7aa53be7c72..c7f924e8ba2bd0 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index e92a9aab1928c8..564b741812351b 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index ef7c19dc1b7fea..79c9eda7c7be54 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 680c70e75c0601..b37b1655b90657 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -7760,7 +7760,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { success: boolean; }, ", + ", { id: string; name: string; description: string; time_window: { duration: string; is_rolling: true; }; indicator: { type: \"slo.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"slo.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; }; budgeting_method: \"occurrences\"; objective: { target: number; }; settings: { destination_index?: string | undefined; }; }, ", { "pluginId": "observability", "scope": "server", @@ -7948,7 +7948,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { success: boolean; }, ", + ", { id: string; name: string; description: string; time_window: { duration: string; is_rolling: true; }; indicator: { type: \"slo.apm.transaction_duration\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; 'threshold.us': number; }; } | { type: \"slo.apm.transaction_error_rate\"; params: { environment: string; service: string; transaction_type: string; transaction_name: string; } & { good_status_codes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; }; }; budgeting_method: \"occurrences\"; objective: { target: number; }; settings: { destination_index?: string | undefined; }; }, ", { "pluginId": "observability", "scope": "server", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 7a1e6c0e0601f9..99becab9902a4f 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 8398670e49a38f..1947693a477662 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index f6762a00b3cc2c..27b2acef31bce6 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 442 | 368 | 36 | +| 450 | 375 | 36 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 30641 | 180 | 20479 | 966 | +| 30721 | 180 | 20533 | 969 | ## Plugin Directory @@ -30,7 +30,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 272 | 0 | 267 | 19 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 23 | 0 | 19 | 1 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 7 | 0 | 0 | 1 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 368 | 0 | 359 | 21 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 369 | 0 | 360 | 22 | | | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 39 | 0 | 39 | 54 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 80 | 1 | 71 | 2 | @@ -41,7 +41,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Cloud Security Posture](https://github.com/orgs/elastic/teams/cloud-posture-security) | The cloud security posture plugin | 18 | 0 | 2 | 3 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 13 | 0 | 13 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Controls Plugin contains embeddable components intended to create a simple query interface for end users, and a powerful editing suite that allows dashboard authors to build controls | 212 | 0 | 204 | 7 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2657 | 1 | 61 | 2 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2657 | 1 | 58 | 2 | | crossClusterReplication | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 102 | 0 | 83 | 1 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 147 | 0 | 142 | 12 | @@ -61,7 +61,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Enterprise Search](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Adds dashboards for discovering and managing Enterprise Search products. | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 114 | 3 | 110 | 3 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | The Event Annotation service contains expressions for event annotations | 170 | 0 | 170 | 3 | -| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 100 | 0 | 100 | 9 | +| | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 106 | 0 | 106 | 10 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'error' renderer to expressions | 17 | 0 | 15 | 2 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Gauge plugin adds a `gauge` renderer and function to the expression plugin. The renderer will display the `gauge` chart. | 57 | 0 | 57 | 2 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Heatmap plugin adds a `heatmap` renderer and function to the expression plugin. The renderer will display the `heatmap` chart. | 105 | 0 | 101 | 3 | @@ -212,7 +212,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 12 | 0 | 12 | 0 | | | Kibana Core | - | 8 | 0 | 1 | 0 | | | Kibana Core | - | 3 | 0 | 3 | 0 | -| | Kibana Core | - | 20 | 0 | 3 | 0 | +| | Kibana Core | - | 12 | 0 | 3 | 0 | | | Kibana Core | - | 7 | 0 | 7 | 0 | | | Kibana Core | - | 3 | 0 | 3 | 0 | | | Kibana Core | - | 3 | 0 | 3 | 0 | @@ -307,6 +307,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | Kibana Core | - | 66 | 0 | 66 | 4 | | | Kibana Core | - | 14 | 0 | 13 | 0 | | | Kibana Core | - | 99 | 1 | 86 | 0 | +| | Kibana Core | - | 12 | 0 | 2 | 0 | +| | Kibana Core | - | 19 | 0 | 18 | 0 | +| | Kibana Core | - | 20 | 0 | 1 | 0 | +| | Kibana Core | - | 22 | 0 | 22 | 1 | +| | Kibana Core | - | 4 | 0 | 4 | 0 | | | Kibana Core | - | 11 | 0 | 9 | 0 | | | Kibana Core | - | 5 | 0 | 5 | 0 | | | Kibana Core | - | 6 | 0 | 4 | 0 | @@ -398,6 +403,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 5 | 0 | 3 | 0 | | | [Owner missing] | - | 24 | 0 | 4 | 0 | | | [Owner missing] | - | 17 | 0 | 16 | 0 | +| | [Owner missing] | - | 2 | 0 | 1 | 0 | +| | [Owner missing] | - | 1 | 0 | 1 | 0 | | | [Owner missing] | - | 2 | 0 | 0 | 0 | | | [Owner missing] | - | 14 | 0 | 4 | 1 | | | [Owner missing] | - | 9 | 0 | 3 | 0 | @@ -407,7 +414,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [Owner missing] | - | 4 | 0 | 2 | 0 | | | Operations | - | 38 | 2 | 21 | 0 | | | Kibana Core | - | 2 | 0 | 2 | 0 | -| | Operations | - | 253 | 5 | 212 | 11 | +| | Operations | - | 254 | 5 | 213 | 11 | | | [Owner missing] | - | 135 | 8 | 103 | 2 | | | [Owner missing] | - | 72 | 0 | 55 | 0 | | | [Owner missing] | - | 8 | 0 | 2 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index bd88e5f88c6ffd..bc7c76f0a0c955 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 4dc8865027be98..88da0bf6a4084d 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 98619fec51a28f..74b1dd2f9b3d73 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 32c76e983e404c..79ae29b7cd9634 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 0c20752827038f..5d356a047e0f8f 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 3da2926bef45d4..8e691c449fa90e 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index ccb2436bc7ab51..fb05689cecd020 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 8ebb9e956a9bd1..3e1a0c5cac8dbb 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 96fc861f282ecf..4b92df6269c8f4 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index f1f07a53b63c0d..b478c993aec5a7 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 10469dabcc739c..d066af233eaa05 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index e0fd13863fddb3..67f6e1447557d9 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index ab9308881edad5..e997282c0b6e05 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 25835a28fb913b..6d738d3ef7b257 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 7aeaddd49f9fc2..d77a427d28d03f 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index f2e9de3b4461d9..850b23354ce986 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index a0b46b34aff8c2..4bd6c8ea81ccf9 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 917ac7b5c8b7aa..fbd92de7c18e33 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 3d2d4e9f7d91bb..c8c3606dd8e9b9 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 039252a8b5f89e..a0a381d3172c4f 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index e1bbb20979c05e..b2619a5e99e09d 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 6f5a5d420ec861..d2905a302b3740 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index fe725f5cd654d4..c804bf99901367 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index c510c72159d824..49f4d89ec5bd8f 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 79bcdf8736b5d0..5b29098952f778 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index a79d78af7bd71b..594bd8e6e25140 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 5a830485f55ec6..03ffe572bc60c7 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index e8be0345a839ff..729e3cc82c26eb 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index d53e2f51177d78..ec7747ab73d4e9 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 97a09460258c2e..0f3ecb6391ebb5 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index e95f3879bfb834..15625ed9a811c8 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 477dcd64c4e87e..75e2299f8583ef 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index f2fbbc473c25c0..926dbd529e6e11 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index c14315f59ce5ab..73636fd0965d15 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 74c9ed470c1f10..abbad21fb3a9d7 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index b9c921a284d1d1..c086fe973e1ecc 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 4de9f1cf325bfd..747a230f0e7c64 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index d497f6bb0a4466..c59213764f79ab 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 1237c1960ae3bd..273e849b4a232e 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 54d7da6ff41a93..20c8ee5c76e457 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 48c4485641f9b5..0d13f8c5ebd84d 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index f03b8bea14f0b6..4dba7024de942e 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index db63128f3733ec..7d4ff7d4b09f0c 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 3767eed28f79c3..517a86689b15ad 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index eaa8be6fe9eaa5..0b81c3a76a2868 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 56642da0d7bb1d..44dac9a54417c6 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 20e284f805f36e..0f7d4fcd624925 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index d7a9c73ca02656..706467a384a47f 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index d708564591c581..4061ad954517bf 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-09-09 +date: 2022-09-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 95beca7d72f62b67cdf95d73739d2160e61f6ae6 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Sat, 10 Sep 2022 22:40:09 -0600 Subject: [PATCH 044/144] [api-docs] Daily api_docs build (#140461) --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/core.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- api_docs/kbn_alerts.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx | 2 +- api_docs/kbn_analytics_shippers_elastic_v3_common.mdx | 2 +- api_docs/kbn_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- api_docs/kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- api_docs/kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- api_docs/kbn_core_application_browser_internal.mdx | 2 +- api_docs/kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- api_docs/kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- api_docs/kbn_core_deprecations_browser_internal.mdx | 2 +- api_docs/kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- api_docs/kbn_core_deprecations_server_internal.mdx | 2 +- api_docs/kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_client_server_internal.mdx | 2 +- api_docs/kbn_core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- api_docs/kbn_core_elasticsearch_server_internal.mdx | 2 +- api_docs/kbn_core_elasticsearch_server_mocks.mdx | 2 +- api_docs/kbn_core_environment_server_internal.mdx | 2 +- api_docs/kbn_core_environment_server_mocks.mdx | 2 +- api_docs/kbn_core_execution_context_browser.mdx | 2 +- api_docs/kbn_core_execution_context_browser_internal.mdx | 2 +- api_docs/kbn_core_execution_context_browser_mocks.mdx | 2 +- api_docs/kbn_core_execution_context_common.mdx | 2 +- api_docs/kbn_core_execution_context_server.mdx | 2 +- api_docs/kbn_core_execution_context_server_internal.mdx | 2 +- api_docs/kbn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- api_docs/kbn_core_http_context_server_mocks.mdx | 2 +- api_docs/kbn_core_http_router_server_internal.mdx | 2 +- api_docs/kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- api_docs/kbn_core_injected_metadata_browser.mdx | 2 +- api_docs/kbn_core_injected_metadata_browser_mocks.mdx | 2 +- api_docs/kbn_core_integrations_browser_internal.mdx | 2 +- api_docs/kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_collectors_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- api_docs/kbn_core_notifications_browser_internal.mdx | 2 +- api_docs/kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- api_docs/kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_api_browser.mdx | 2 +- api_docs/kbn_core_saved_objects_api_server.mdx | 2 +- api_docs/kbn_core_saved_objects_api_server_internal.mdx | 2 +- api_docs/kbn_core_saved_objects_api_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_base_server_internal.mdx | 2 +- api_docs/kbn_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- api_docs/kbn_core_saved_objects_browser_internal.mdx | 2 +- api_docs/kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- .../kbn_core_saved_objects_import_export_server_internal.mdx | 2 +- api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_migration_server_internal.mdx | 2 +- api_docs/kbn_core_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- api_docs/kbn_core_saved_objects_server_internal.mdx | 2 +- api_docs/kbn_core_saved_objects_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- api_docs/kbn_core_test_helpers_deprecations_getters.mdx | 2 +- api_docs/kbn_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_internal.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- api_docs/kbn_core_ui_settings_browser_internal.mdx | 2 +- api_docs/kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- api_docs/kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_get_repo_files.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_alerting_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- api_docs/kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_analytics_no_data.mdx | 2 +- api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_kibana_no_data.mdx | 2 +- api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_kibana_template.mdx | 2 +- api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_config.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- api_docs/kbn_shared_ux_prompt_no_data_views.mdx | 2 +- api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_package_json.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_type_summarizer.mdx | 2 +- api_docs/kbn_type_summarizer_core.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 2 +- api_docs/presentation_util.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_field_list.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 382 files changed, 382 insertions(+), 382 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index d5c6c13ca391b5..3025e3c667a605 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 7133dfd6c85cd3..a9f6922f31c0d9 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index dc7c5c036cacce..877f5f0d599125 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 445e6f8b161d04..969deada62d833 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 87a44cde46dfc8..031ff7c280dc6f 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index fecb09b91403a3..e02969f5caba7a 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 31934ad54f169d..d6497fb8300dc6 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index b65e73ac957fd4..f02bf545e8e1c1 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 4ab29be190d884..e383d536d3839d 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index f280cd886f8075..8a9e27d98094a4 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 7647e574a0489e..c5c83271b18d3a 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index d700f715cd5fcb..fb001228fa3f46 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 596ad1ce6d85d9..b9047f4a24a4a9 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 4f085837f13179..6da5ee9f0746da 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 8493bbeb60153f..204d2415d2b7e7 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index a9828ba77768c1..8cd3ce3704b80e 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index ed6401ee90e45b..1c7d146485765c 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 57403c81c804f6..aae133a2412204 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 3fdc8ef0dce571..c211da19b2a495 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 05ce7913fdb1f4..ade7e083d84bc6 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 0bd7f60c7859d1..f6c931e4cec1a2 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index d31af9be4e4a72..6744db8e790c79 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index e9b13996dac8cc..224ac3dfcb2dd8 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index 8bc524181fa7fb..d5d199ff46ba19 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index a222c1751a304e..9b05096958466d 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index ae2db4b7642391..24fee647eeb7f8 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index aae826f6eabd0c..0e9744507654c6 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index ccddf195d99cd4..a350a7959739ab 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 2ca551b49fc6c0..5ebeeae4c53dc7 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 090051819ee525..7b8f1654a1d64f 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 6201c3124a2333..1d250c38c549c4 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index d6f701b24d111e..d12e6c092ab7db 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 81db63354eed8b..f382a16c0f09f6 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index e8be99273583db..a2e50f21c7e264 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 1f9272fc71406a..b1d1432f6b4c7a 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 520fe453576b44..ecde934e30affb 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 890f44f48dfcca..976cd3fddd0976 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 41817a2babd3f2..b9ce5e25248335 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index af0b5490c3e3e0..b914b0c80cf12d 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 3e0211b9f284c6..8a494564e676a5 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 4794e6477d61b0..4e9ab427950b2e 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 8ce939920ce5c0..e4fe738d7d291e 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 491323f11e1c61..c71511b96c318e 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index c4a81fbce92559..33ba87eb7b5f3f 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 00cdc709d7d433..3bfd49a0a0ab52 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 7ce33c3dc83513..f1d49dc44f8ddd 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index e3f630ad08eada..b6d68cb2b323e8 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 65dcbadeb689b5..c6b1df89b1360d 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 680c7be5ac3b48..b2e2ad2f8444ef 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 61096294f663a3..c150b5f41465fc 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index b59a856511bd1e..28f009516b4190 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 7b984b1b3ced18..56897b6597827a 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index c5db0bef7dc547..5a8e3138f08124 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index ad7f8812cd8b86..e038774bfa9374 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 864e17ba18d7f5..92e0207fbd8be6 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index b9f59064095fd1..60ec7732acd75f 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 2a3701b79c6d76..a6d8d632ff9b01 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index c444592ed14ab7..c53e062e643a8a 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 838b35681ace20..5ed82a919fcd6c 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index b81ea75cfaaf8d..5bbe2b58a1accd 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index dcda22c9b4e00e..0a59397f0c068a 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index a7983f72580bcb..81c79814547423 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 09d0183b9151d1..4920906b8fcdd5 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 4a00d6265c95d4..9c5867adf2e443 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 5edde61b03b304..e75e271da43f16 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index c6419c2f9a0db5..a86d6e9cba7a55 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 4c04ff932864d3..757980d3e6c938 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index d846738129acd2..0b69c7a96e6c4d 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index aad3ebee739701..7f5fa0c4a8cd78 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 5239dceb0b4b15..2b5a1eed6ec3f7 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 3549300cebec0a..ec2a36eb92df78 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index f31e192ad5409b..f75dae8740f9a4 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index 6dcf2355e33221..d4a81f43dc82f7 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 3abb48ffa29f94..429b53bdf7e101 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 596bbea03e8a70..4c4cb3cf3efa2b 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index b29cb6fc67bf47..f1e62abb86ab14 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index f667c806918400..4e062859cb0b1c 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 2429ab10684b29..a7a506ce86fc25 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index b09e1e8ec196f1..6b570ab3aab8c2 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index c993682371dd1e..0cfd4d21feb792 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 34ab9ce22db435..fc833e10f26853 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index a656c6f017a596..e26a00304d9a0f 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 62069d98c55501..cf6f7a950ad551 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 4086bede91f505..eb21786d914dde 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 8bfb510cb4fa18..01f5e595c9dd38 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 5a928943d1e94d..52bc3424f9e013 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index d5e32b85b786fe..79413342ab401f 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 84f3f19cf92ece..a85abe0d1f4629 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 457bb48fbcdc19..91991ec18f8845 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 0afa1ba8252404..473131110b37d5 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index baad9a7e2452dd..5109686b45e4b6 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 3e71f0cc873c78..94e10b46f2316c 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 1d1dafb69871bf..bc0f9edc666711 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 31d93967d234db..ba57a73b999421 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 06c0a6252f8605..3fa4da5936b38a 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 167b9518fbfdd5..51c111c7988f76 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 027dc4ea5eb7b5..1b76d387f45098 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index b3a70181b0c2d0..f6e23ad2b383cf 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index f96bd7d5c5e6ea..07637ebdaf7c01 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 368a5dd0008cac..d35d7443a193eb 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 6d155ce49d85ea..34e28daec02d0d 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 66f5f7450be48b..c739147712e761 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 3ce0e791b74649..0461dd4be981f0 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 7c6f27244f0d7a..2e725a63445363 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 3849e728af3e27..430137c8d9959d 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index 91a0837f38318e..fce198d30b8a7d 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 724e892be1c60b..083977d68e52fc 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index 25d6e2dae632f9..80d56506102423 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 5727d5efa48df1..6ac42a81cccaa5 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 39ec5296fe70ec..d81872b86ed9fa 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 74e947bc8463da..74d33cc2a26e24 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index e91fb82f806103..6a273e0bbc6400 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 70564fe13edbbb..2dc2bbdec82d5d 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 91f7162c82f7ed..2cfda1b1e14f51 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 8073bb4836752f..26aee3b1d9481b 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index 5678298ca733c3..daf442ebc26b46 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 96f7ecec3bc42d..7a1c650f01e582 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 824030f1daa252..c1d20b550cd001 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index db5d060f35a8d8..3af31403f23ace 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 1780ab586e6490..9b92df3210b123 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 11ccbdd98c2f3b..b1ef52b7dc5e7a 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index c698d02940bcf9..b7cebd8cb78697 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 0c8b555c777211..d5a72fb8c9f7a2 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 92e416c29bf95b..d8e28509d3f6df 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 37c2becd7354ba..a20a4f29e62352 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 390a061c8981c5..dbc1a29005b263 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index b42023a54f6152..64faca1523441a 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 9ab334b2c6624f..a8866f07127b85 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 8787f12bceadfc..2cb03493086ef5 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 95ff1d8689a573..e806ee84139e5a 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index aea2f328723ab5..2de4c4665618d2 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index f3764fe8d6f943..7e486b492cb7fb 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 3a1182ada50652..0c29cdee5039d0 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index a4cc0208bd03f9..fabbeb65d0a485 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index a4d41b900aef82..c977778112ccb0 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index c638049a6b3e03..c8454f5f4a1ad7 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index ea182d13d4240c..f90f61f3441829 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index db770a72f35975..644f37bab4f8bf 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 264b5b1a331667..73c5b5e7ab616e 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 1403f95b83599b..90a1d70ad8ebe3 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index f387d4a897882f..41fa8208a1d3d2 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 96020064f61fb8..07e62ce040beec 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 1315293ec65a2c..0e1f4bc4292dd1 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index e1f3750c84a27e..9c661db0a0d4c4 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 53e3dbb94f3604..fdffc72c5de1c6 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 9af745103bea09..adcf42480843ba 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index b8f73ee93016a0..f99d83106c9ba3 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 89a06be37a6fa8..00f2319d95a4d9 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index a396a416f9d749..2036346943a3bc 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 7140c88921d6f7..2430f7709e3f2e 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index 2164762ea7a020..e9e57ae24900b6 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 828f4f1a12d5f0..193a70ee06f5ce 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index c836a584e00952..4d4bde98c08249 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index daf159516318b3..6b8cf748eea9ba 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index b19ffe7e38b18d..b470dc449dd954 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index cd01fd52739292..23ce8cc600f0e9 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 150968cb0570e9..fa7a24d11ac1fe 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 788e4f701670f8..f137c3dccec8a7 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 8101e973753e8f..8911ce825c3480 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 94799690c450d7..f4f423d7181cb2 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 7a3515639112ec..a99659d4c5b9fb 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index c2a89783ff2339..d0ea7ef6101557 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 3635d788ab55c0..239347724a16b2 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 9e3162a0eee92f..38f9308d189240 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 4c2b69880d9b78..c4091bcd35f9b6 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index b89677d1be7437..7e34262d8bb258 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 742de4384ddd0e..4ae04538bb07ee 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 8621952d15a633..7ceeca5e39b67a 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 518d5c12f5d68b..8b580261d449ba 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 6210a65c921594..5de3e5441f0a3a 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 2f7ec5fe4f2e06..c9a8a6fa296fb4 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index e9a8d04e8c4629..e21ba36217cdb8 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 0cb0033765ac1c..24be1762c920d3 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 08c1e192449f67..a441e2ef32789a 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index c1665898b331dd..8a5919dd59d977 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 50fa0b1303d191..b838876f7f7476 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 01133a602b6168..bfcbeb55a18b88 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 63a4b1b1afc781..66abe1a3927010 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index 0052df5199754d..904a4b379dcf10 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index fb4b4c5e400251..1fc8fea5658dec 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 0c7b97f3d40aa1..4db9b280efd7af 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 8a0f130084dcc2..bf1cb01f73a28b 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 57a308d4daba91..1afe62c5c2ce8f 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 0585dfbd2b21a5..70950894bcedc0 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 20980722e5e605..59dc76b98636e3 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 0f69c3872f40b7..5892c9fb0a0167 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index b67d4011f24c57..c407dcb5e295a7 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 1444f1dc2bebab..dc9525f01b09b8 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index a20cf1a5fb3b9a..2ce5252fd39dfa 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index c5399214f2edff..2ffdb6dc3ce24f 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 3560b5d875cc38..2b67fbdd407222 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 60d095cdc08424..e3395e86dae43d 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 8c065c5e187c64..bbff1bf85dbbd1 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index e48205627b9089..396a6320edec5b 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index bde6925ddfcf2d..e538113de3fac6 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index f8b8988e0f703e..58ed0073a4cd91 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 92b56d4cc62fe8..36d33ea9b1a749 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 2d6ea32e7361d8..687cebf362c2ad 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index bdfe6900db761d..0c8d201b108db7 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index f21f50e4be1fe9..01b7c9b7547267 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index 15647342dddb06..2c23d98be0d556 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 36e37f77a6194d..ae8a3bb99e2318 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index fe02ab842adba8..f66d8b9d925c2c 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index ca472346327829..60daee6a7d7e5a 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index a6c20f54519d53..6a9cf22463b094 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index acc89049462fb6..cbf6d686988729 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 66cb9a0b33eb02..400a2273ebb48f 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 662fd7c508ba71..a580f88ebdfe1a 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 8c88455d9b0926..74de25b9936b3c 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 13bab0f2ea1fc1..45af778aabb7a0 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 5d4a2904c9b548..cc570f84b5efa6 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 2c449d15974bf3..189fd0164bfe1b 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 01d0f9a9a6a321..436322f7854287 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index dfea5cf2ab2026..7a5442a1a0cae5 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 85cc9c38bd3315..e9fa94182c598e 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 95b42536984fa2..3218754cc239cc 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index e841f9170a1fd0..010511da8532e1 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index f23422a1b253ad..d9e2807bff8938 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 57fbccecd3fdd6..cd39f7f26935e5 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index d4b4c39f2de253..3b1835f359eb85 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index cbf92ce5c96347..597ccfe2be00e2 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index ae6572d784a590..1604ebb3ec2e37 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 7a52f9e558bfd4..1bf6e2f7f5a006 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index b7944a7d94e9ee..e24c7591af75bf 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 6040010dd50e45..4215f85c6f8c53 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index c9cea912963a81..c9bfd3ca76b144 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index a129022994df3e..ba1864c2dc58d2 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index b578add112d054..645ca3d359c8bb 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index fa2b54e14253b1..ddd1905cc7047b 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index a538f4419085b2..99dd8ebca16535 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 2d7dfddb7cfde4..d9efa7441aa9b6 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 78bd769b5616fe..936f1dee9f1e43 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 4555f95d1db3ab..05349d6c8ba5cc 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index f4bb9bdaa32f21..529512b81500c2 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 305d42d10b555c..ec7d13bd2af088 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 9ff24d656b6f57..fa531348925610 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index c4eced5115fbc1..d72524950d40e0 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 6eee5a2ddc9594..c30d18c57d28f6 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index d449b34a0d001b..088b7c3ab3e51e 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 41fdb074db3083..3b262cbc1a1e84 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 88fdd1d8a30cda..d0805d8f0e3a7f 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 4d281617212ead..49721d1cea988a 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index ccd82c4552dab0..1156a351ae27f0 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index c277f36bd68900..f96c7fb58804f0 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index b8068d9717b684..306793a3ad5578 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 5fad0d1b3c6192..fb0f0be2270ffe 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index e02e85e387df33..7591ffa38ef80d 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index b26e5b25de93b8..322849b06d34f2 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index 236351581f68d4..c9b0d4fe6a0ac9 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 24abda1b0c6e73..668f0851dbfa57 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index e01f3f99ffd81f..bd11c64056cf7c 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 6e2679e6ac26df..cd76e179c4559d 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index e7571b2b5f2db5..2e09a5e871c858 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index e31a33e2ae566a..415a5ae710a72d 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index d96fa6a177e2f4..9807368001ea3b 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 47327f749fc93b..2db12aca59f5e5 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index c6699b94b8a399..8857544c0305a4 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 1820e21e88d48d..d9498bc90ca629 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index b5c97c6c0e1985..9d7b8f7633c3b8 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 5f500a432f34fa..8670181ea26180 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 256a6591902899..dae3809a97f6e0 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index ed97855cf35483..45dc38e5c6942c 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 2b84ca3272b691..e5f1b8291164bd 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 9f7dcd57ae65a7..8f20caaeb9cae1 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index abd918eb8d3985..8344e032aad540 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 4a53f6921c66c6..f1bf9b41313027 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 426a1bbc586abf..ade345bb5615dd 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 17dd013084ddde..447ee7b71c7e2d 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index c1a403fe7e707b..5c71c74ae942c0 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index be4755193af441..10400f212cfcf4 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 7554a6a18493d7..0fee8a03fa8703 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 142a54239e5517..f0b51e26b5ad69 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 1797e343347d88..2609283ac184eb 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 8364ea1f8c53be..08fc2716208596 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 26110f7aa404d7..81c4323ef5b3ff 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index ffa50fa47a0f7d..c6b4f08bec31a8 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 757355b8211db6..f827d296d95f7b 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 726fe4c091d14c..76fa4162e4659a 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index dc28f2e50ce658..e6532bbf960c50 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 5a0615a5e3b884..52ccc629f932ca 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 128001d9f7a5de..34dac5295a708c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index a491b3eef50b9c..21df75d4ceec4e 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index eb074d07ee15bf..5cf068205b142f 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 7b3a8439e29e08..9975f552e2d184 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 1b151f3099a00b..fd907ad4acd667 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 7690985e6c9f7f..8f006ae13ac7fd 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index 5c27ce9906bfd6..ae83d0e7fe3b7a 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 08f8c0ea2414f2..9e345e8fb66ff2 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index b7b14058fc47e8..d60e9ac96d2803 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 4670ab6757530d..96cc446e6fefb6 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 90e7d25f00b892..24567ffdf3445b 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 5dff7d8731cd4a..46ecfc817267f2 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index aa5ef51758ba33..8af04a8805463c 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 194fe83ad1f38a..0150f05323bba3 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 5a16ff03fb9901..c6fa1e5cc264db 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 105a4ef0ec531e..fae6e16ab92a53 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 71ffb06e4a78f7..8e8ab3618f788b 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 05262ee2da8542..faf5cee741994d 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 99e1dfc8e1cb02..8751ba41cac845 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index cf3152a814a0d9..2e430f9d0266d8 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 6e824fa356773d..17572df2363419 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index aa87ac4e7d9123..6d6d8317f0e551 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 9de5f0f3f5929e..f4d7dd3e0f4e15 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 6285f1eac7ef09..8c5ef3203612dd 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index 6d71d005ef8877..078368ad360139 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index 93d680eec7468b..df03b17c3ae0f7 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 53fbfddd18b59d..9e9f1254c74611 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index fa8178a8e940ec..cce7fbc5689fd3 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 32cbe5fc75ada9..594491fdecc8bd 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index e594effff18d19..36d9451444b3e7 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 4d779ad075df5b..4feba3b38f7593 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index 5027bcad2b28b7..a157a01b3c9a6b 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index a18c550e611328..a97469db4181d7 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 952430c15e7dd2..e1be4466c01de9 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 934fab6cb77a24..50f5703693a3de 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 3db1b04623d64c..52b62a9bc69a49 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index cc1da70e185089..25d86a53be826d 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 9c97fda0e603cf..573d944ceebb59 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 8289ecb41a7b2c..fc72f81f23e7b0 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index b2739110c8138c..01d17ee704f7cc 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 683099eee4fec9..b0c5f348b512bc 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index c66d0b73906be3..9e0b6900d20978 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 03690c74dc10f8..157780cd018b86 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index b3579c2abc9d06..3319ee23629ef4 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 3381ec2ec9efca..e9978c6653cb9c 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index b20466ec2a9979..c3fb959fdf6b5d 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 1fc969c65cd8cc..07fad65fc3b271 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index c7f924e8ba2bd0..bb16b57ac9e244 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 564b741812351b..fd9c6c30b99a1d 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 79c9eda7c7be54..c788ba9e7f6231 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 99becab9902a4f..db53834bfe1342 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 1947693a477662..07b26fd92d2b6f 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 27b2acef31bce6..c12a7b23b50daa 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index bc7c76f0a0c955..e8fcd477b4023f 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 88da0bf6a4084d..c2adbf5d4b6884 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 74b1dd2f9b3d73..ec9abe0f75103c 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 79ae29b7cd9634..b36bcf7dcf04d7 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 5d356a047e0f8f..fcb98184ac721a 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 8e691c449fa90e..2d29a830ac2107 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index fb05689cecd020..54366ae393ceb9 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 3e1a0c5cac8dbb..01b865e133a773 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 4b92df6269c8f4..ed0eb8d662405f 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index b478c993aec5a7..c26048db692895 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index d066af233eaa05..e3f02c8e029885 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 67f6e1447557d9..a6487b37023814 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index e997282c0b6e05..4a39fa9cdd5619 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 6d738d3ef7b257..74ba599fc51b36 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index d77a427d28d03f..81eee14edb1fb7 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 850b23354ce986..dad1dd94bbd4dc 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 4bd6c8ea81ccf9..22fac81e890237 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index fbd92de7c18e33..07e5942620fc3e 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index c8c3606dd8e9b9..a775f63cffd49e 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index a0a381d3172c4f..ec94eb7b7ec89f 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index b2619a5e99e09d..4124b573463298 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index d2905a302b3740..3bc27698a60367 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index c804bf99901367..66be10fc270cd1 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 49f4d89ec5bd8f..75102dbc52f82c 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 5b29098952f778..c848059af41e09 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 594bd8e6e25140..2d383534e6173a 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 03ffe572bc60c7..3f6612eeb70903 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 729e3cc82c26eb..601adbcdf93833 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index ec7747ab73d4e9..55b6299dfd4779 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 0f3ecb6391ebb5..e69614e09b29e6 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 15625ed9a811c8..603903b5e16845 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 75e2299f8583ef..f82809f791062d 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 926dbd529e6e11..a44e9ef13c884b 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 73636fd0965d15..a03b99f1f280b6 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index abbad21fb3a9d7..46cbdd7c383542 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index c086fe973e1ecc..e4353912664717 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 747a230f0e7c64..514bfd452f0c4a 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index c59213764f79ab..5e0571a91b3bed 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 273e849b4a232e..88ceeaf9a67b0d 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index 20c8ee5c76e457..b4590576a445e8 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 0d13f8c5ebd84d..688644059d558d 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 4dba7024de942e..e683cc9d59d0cc 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 7d4ff7d4b09f0c..65bd5ac3f83eb1 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 517a86689b15ad..569b354b761a6b 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 0b81c3a76a2868..362e6fa9159ff0 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 44dac9a54417c6..de331861fc09e2 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 0f7d4fcd624925..197508c600b5c2 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 706467a384a47f..e4d1de0d28a318 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 4061ad954517bf..72cff108cef000 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-09-10 +date: 2022-09-11 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From a171f93995ab99b06e6612ad11e02b0828a36b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Sun, 11 Sep 2022 20:20:58 +0200 Subject: [PATCH 045/144] [Security Solution] Add Osquery markdown plugin (#95149) --- .../public/live_queries/form/index.tsx | 142 +-------- .../form/live_query_query_field.tsx | 151 ++++++++-- .../queries/ecs_mapping_editor_field.tsx | 50 ++-- x-pack/plugins/osquery/public/plugin.ts | 12 +- .../saved_queries/saved_queries_dropdown.tsx | 2 +- .../public/shared_components/index.tsx | 1 + .../lazy_live_query_field.tsx | 39 +++ .../shared_components/lazy_osquery_action.tsx | 25 +- .../osquery_action/index.tsx | 57 +--- .../osquery_action/osquery_action.test.tsx | 7 - .../shared_components/services_wrapper.tsx | 36 +++ x-pack/plugins/osquery/public/types.ts | 3 +- .../investigation_guide_view.tsx | 12 +- .../markdown_editor/plugins/index.ts | 22 +- .../markdown_editor/plugins/osquery/index.tsx | 273 ++++++++++++++++++ .../plugins/osquery/label_field.tsx | 49 ++++ .../plugins/osquery/osquery_icon/index.tsx | 19 ++ .../plugins/osquery/osquery_icon/osquery.svg | 13 + .../markdown_editor/plugins/osquery/utils.ts | 31 ++ .../components/osquery/osquery_flyout.tsx | 69 +++-- .../side_panel/event_details/helpers.tsx | 13 +- 21 files changed, 722 insertions(+), 304 deletions(-) create mode 100644 x-pack/plugins/osquery/public/shared_components/lazy_live_query_field.tsx create mode 100644 x-pack/plugins/osquery/public/shared_components/services_wrapper.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/label_field.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/index.tsx create mode 100755 x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/osquery.svg create mode 100644 x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/utils.ts diff --git a/x-pack/plugins/osquery/public/live_queries/form/index.tsx b/x-pack/plugins/osquery/public/live_queries/form/index.tsx index 3ed54c451f38b9..96afe9deb98e2e 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/index.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/index.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import type { EuiAccordionProps } from '@elastic/eui'; import { EuiFormRow } from '@elastic/eui'; import { EuiButton, @@ -13,16 +12,15 @@ import { EuiSpacer, EuiFlexGroup, EuiFlexItem, - EuiAccordion, EuiCard, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import { useForm as useHookForm, FormProvider } from 'react-hook-form'; - import { isEmpty, map, find, pickBy } from 'lodash'; import { i18n } from '@kbn/i18n'; + import type { SavedQuerySOFormData } from '../../saved_queries/form/use_saved_query_form'; import type { EcsMappingFormField, @@ -33,8 +31,6 @@ import { convertECSMappingToObject } from '../../../common/schemas/common/utils' import { useKibana } from '../../common/lib/kibana'; import { ResultTabs } from '../../routes/saved_queries/edit/tabs'; import { SavedQueryFlyout } from '../../saved_queries'; -import { ECSMappingEditorField } from '../../packs/queries/lazy_ecs_mapping_editor_field'; -import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown'; import { usePacks } from '../../packs/use_packs'; import { PackQueriesStatusTable } from './pack_queries_status_table'; import { useCreateLiveQuery } from '../use_create_live_query_action'; @@ -99,13 +95,6 @@ const StyledEuiCard = styled(EuiCard)` } `; -const StyledEuiAccordion = styled(EuiAccordion)` - ${({ isDisabled }: { isDisabled?: boolean }) => isDisabled && 'display: none;'} - .euiAccordion__button { - color: ${({ theme }) => theme.eui.euiColorPrimary}; - } -`; - type FormType = 'simple' | 'steps'; interface LiveQueryFormProps { @@ -123,7 +112,6 @@ const LiveQueryFormComponent: React.FC = ({ defaultValue, onSuccess, queryField = true, - ecsMappingField = true, formType = 'steps', enabled = true, hideAgentsField = false, @@ -161,8 +149,6 @@ const LiveQueryFormComponent: React.FC = ({ [permissions] ); - const [advancedContentState, setAdvancedContentState] = - useState('closed'); const [showSavedQueryFlyout, setShowSavedQueryFlyout] = useState(false); const [queryType, setQueryType] = useState('query'); const [isLive, setIsLive] = useState(false); @@ -208,43 +194,14 @@ const LiveQueryFormComponent: React.FC = ({ [queryStatus] ); - const handleSavedQueryChange = useCallback( - (savedQuery) => { - if (savedQuery) { - setValue('query', savedQuery.query); - setValue('savedQueryId', savedQuery.savedQueryId); - setValue( - 'ecs_mapping', - !isEmpty(savedQuery.ecs_mapping) - ? map(savedQuery.ecs_mapping, (value, key) => ({ - key, - result: { - type: Object.keys(value)[0], - value: Object.values(value)[0] as string, - }, - })) - : [defaultEcsFormData] - ); - - if (!isEmpty(savedQuery.ecs_mapping)) { - setAdvancedContentState('open'); - } - } else { - setValue('savedQueryId', null); - } - }, - [setValue] - ); - const onSubmit = useCallback( - // not sure why, but submitOnCmdEnter doesn't have proper form values so I am passing them in manually - async (values: LiveQueryFormFields = watchedValues) => { + async (values: LiveQueryFormFields) => { const serializedData = pickBy( { agentSelection: values.agentSelection, saved_query_id: values.savedQueryId, query: values.query, - pack_id: packId?.length ? packId[0] : undefined, + pack_id: values?.packId?.length ? values?.packId[0] : undefined, ...(values.ecs_mapping ? { ecs_mapping: convertECSMappingToObject(values.ecs_mapping) } : {}), @@ -259,25 +216,7 @@ const LiveQueryFormComponent: React.FC = ({ } catch (e) {} } }, - [errors, mutateAsync, packId, watchedValues] - ); - const commands = useMemo( - () => [ - { - name: 'submitOnCmdEnter', - bindKey: { win: 'ctrl+enter', mac: 'cmd+enter' }, - // @ts-expect-error update types - explanation in onSubmit() - exec: () => handleSubmit(onSubmit)(watchedValues), - }, - ], - [handleSubmit, onSubmit, watchedValues] - ); - - const queryComponentProps = useMemo( - () => ({ - commands, - }), - [commands] + [errors, mutateAsync] ); const serializedData: SavedQuerySOFormData = useMemo( @@ -285,23 +224,6 @@ const LiveQueryFormComponent: React.FC = ({ [watchedValues] ); - const handleToggle = useCallback((isOpen) => { - const newState = isOpen ? 'open' : 'closed'; - setAdvancedContentState(newState); - }, []); - - const ecsFieldProps = useMemo( - () => ({ - isDisabled: !permissions.writeLiveQueries, - }), - [permissions.writeLiveQueries] - ); - - const isSavedQueryDisabled = useMemo( - () => !permissions.runSavedQueries || !permissions.readSavedQueries, - [permissions.readSavedQueries, permissions.runSavedQueries] - ); - const { data: packsData, isFetched: isPackDataFetched } = usePacks({}); const selectedPackData = useMemo( @@ -309,6 +231,8 @@ const LiveQueryFormComponent: React.FC = ({ [packId, packsData] ); + const handleSubmitForm = useMemo(() => handleSubmit(onSubmit), [handleSubmit, onSubmit]); + const submitButtonContent = useMemo( () => ( @@ -330,7 +254,7 @@ const LiveQueryFormComponent: React.FC = ({ = ({ handleShowSaveQueryFlyout, enabled, isSubmitting, - handleSubmit, - onSubmit, - ] - ); - - const queryFieldStepContent = useMemo( - () => ( - <> - {queryField && ( - <> - {!isSavedQueryDisabled && ( - <> - - - )} - - - )} - {ecsMappingField && ( - <> - - - - - - - )} - - ), - [ - queryField, - isSavedQueryDisabled, - handleSavedQueryChange, - queryComponentProps, - queryType, - ecsMappingField, - advancedContentState, - handleToggle, - ecsFieldProps, + handleSubmitForm, ] ); @@ -589,7 +467,9 @@ const LiveQueryFormComponent: React.FC = ({ ) : ( <> - {queryFieldStepContent} + + + {submitButtonContent} {resultsStepContent} diff --git a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx index e3516f982cc0b3..2938251e177be2 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx @@ -5,33 +5,45 @@ * 2.0. */ -import { EuiCodeBlock, EuiFormRow } from '@elastic/eui'; -import React from 'react'; +import { isEmpty, map } from 'lodash'; +import type { EuiAccordionProps } from '@elastic/eui'; +import { EuiCodeBlock, EuiFormRow, EuiAccordion, EuiSpacer } from '@elastic/eui'; +import React, { useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; - -import { useController } from 'react-hook-form'; +import { useController, useFormContext } from 'react-hook-form'; import { i18n } from '@kbn/i18n'; -import type { EuiCodeEditorProps } from '../../shared_imports'; import { OsqueryEditor } from '../../editor'; import { useKibana } from '../../common/lib/kibana'; import { MAX_QUERY_LENGTH } from '../../packs/queries/validations'; +import { ECSMappingEditorField } from '../../packs/queries/lazy_ecs_mapping_editor_field'; +import type { SavedQueriesDropdownProps } from '../../saved_queries/saved_queries_dropdown'; +import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown'; + +const StyledEuiAccordion = styled(EuiAccordion)` + ${({ isDisabled }: { isDisabled?: boolean }) => isDisabled && 'display: none;'} + .euiAccordion__button { + color: ${({ theme }) => theme.eui.euiColorPrimary}; + } +`; const StyledEuiCodeBlock = styled(EuiCodeBlock)` min-height: 100px; `; -interface LiveQueryQueryFieldProps { +export interface LiveQueryQueryFieldProps { disabled?: boolean; - commands?: EuiCodeEditorProps['commands']; - queryType: string; + handleSubmitForm?: () => void; } const LiveQueryQueryFieldComponent: React.FC = ({ disabled, - commands, - queryType, + handleSubmitForm, }) => { + const formContext = useFormContext(); + const [advancedContentState, setAdvancedContentState] = + useState('closed'); const permissions = useKibana().services.application.capabilities.osquery; + const queryType = formContext?.watch('queryType', 'query'); const { field: { onChange, value }, @@ -43,7 +55,7 @@ const LiveQueryQueryFieldComponent: React.FC = ({ message: i18n.translate('xpack.osquery.pack.queryFlyoutForm.emptyQueryError', { defaultMessage: 'Query is a required field', }), - value: queryType === 'query', + value: queryType !== 'pack', }, maxLength: { message: i18n.translate('xpack.osquery.liveQuery.queryForm.largeQueryError', { @@ -56,27 +68,108 @@ const LiveQueryQueryFieldComponent: React.FC = ({ defaultValue: '', }); + const handleSavedQueryChange: SavedQueriesDropdownProps['onChange'] = useCallback( + (savedQuery) => { + if (savedQuery) { + formContext?.setValue('query', savedQuery.query); + formContext?.setValue('savedQueryId', savedQuery.savedQueryId); + if (!isEmpty(savedQuery.ecs_mapping)) { + formContext?.setValue( + 'ecs_mapping', + map(savedQuery.ecs_mapping, (ecsValue, key) => ({ + key, + result: { + type: Object.keys(ecsValue)[0], + value: Object.values(ecsValue)[0] as string, + }, + })) + ); + } else { + formContext?.resetField('ecs_mapping'); + } + + if (!isEmpty(savedQuery.ecs_mapping)) { + setAdvancedContentState('open'); + } + } else { + formContext?.setValue('savedQueryId', null); + } + }, + [formContext] + ); + + const handleToggle = useCallback((isOpen) => { + const newState = isOpen ? 'open' : 'closed'; + setAdvancedContentState(newState); + }, []); + + const ecsFieldProps = useMemo( + () => ({ + isDisabled: !permissions.writeLiveQueries, + }), + [permissions.writeLiveQueries] + ); + + const isSavedQueryDisabled = useMemo( + () => !permissions.runSavedQueries || !permissions.readSavedQueries, + [permissions.readSavedQueries, permissions.runSavedQueries] + ); + + const commands = useMemo( + () => + handleSubmitForm + ? [ + { + name: 'submitOnCmdEnter', + bindKey: { win: 'ctrl+enter', mac: 'cmd+enter' }, + exec: handleSubmitForm, + }, + ] + : [], + [handleSubmitForm] + ); + return ( - - {!permissions.writeLiveQueries || disabled ? ( - - {value} - - ) : ( - + <> + {!isSavedQueryDisabled && ( + )} - + + {!permissions.writeLiveQueries || disabled ? ( + + {value} + + ) : ( + + )} + + + + + + + + + ); }; export const LiveQueryQueryField = React.memo(LiveQueryQueryFieldComponent); + +// eslint-disable-next-line import/no-default-export +export { LiveQueryQueryField as default }; diff --git a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx index 40eb009a71bd1e..7a67c6fdeb65b8 100644 --- a/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx +++ b/x-pack/plugins/osquery/public/packs/queries/ecs_mapping_editor_field.tsx @@ -18,7 +18,7 @@ import { trim, get, } from 'lodash'; -import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import type { EuiComboBoxProps, EuiComboBoxOptionOption } from '@elastic/eui'; import { EuiFormLabel, @@ -625,25 +625,6 @@ export const ECSMappingEditorForm: React.FC = ({ defaultValue: '', }); - const MultiFields = useMemo( - () => ( -
- -
- ), - [item, index, isLastItem, osquerySchemaOptions, isDisabled] - ); - const ecsComboBoxEuiFieldProps = useMemo(() => ({ isDisabled }), [isDisabled]); const handleDeleteClick = useCallback(() => { @@ -676,7 +657,19 @@ export const ECSMappingEditorForm: React.FC = ({
- {MultiFields} + + + {!isDisabled && ( @@ -742,7 +735,7 @@ export const ECSMappingEditorField = React.memo( const fieldsToValidate = prepareEcsFieldsToValidate(fields); // it is always at least 2 - empty fields if (fieldsToValidate.length > 2) { - setTimeout(async () => await trigger('ecs_mapping'), 0); + setTimeout(() => trigger('ecs_mapping'), 0); } }, [fields, query, trigger]); @@ -977,7 +970,7 @@ export const ECSMappingEditorField = React.memo( ); }, [query]); - useLayoutEffect(() => { + useEffect(() => { const ecsList = formData?.ecs_mapping; const lastEcs = formData?.ecs_mapping?.[itemsList?.current.length - 1]; @@ -986,15 +979,16 @@ export const ECSMappingEditorField = React.memo( return; } - // // list contains ecs already, and the last item has values provided + // list contains ecs already, and the last item has values provided if ( - ecsList?.length === itemsList.current.length && - lastEcs?.key?.length && - lastEcs?.result?.value?.length + (ecsList?.length === itemsList.current.length && + lastEcs?.key?.length && + lastEcs?.result?.value?.length) || + !fields?.length ) { return append(defaultEcsFormData); } - }, [append, euiFieldProps?.isDisabled, formData]); + }, [append, fields, formData]); return ( <> diff --git a/x-pack/plugins/osquery/public/plugin.ts b/x-pack/plugins/osquery/public/plugin.ts index 9b8d012e7b084c..ddea34a9361784 100644 --- a/x-pack/plugins/osquery/public/plugin.ts +++ b/x-pack/plugins/osquery/public/plugin.ts @@ -26,7 +26,11 @@ import { LazyOsqueryManagedPolicyEditExtension, LazyOsqueryManagedCustomButtonExtension, } from './fleet_integration'; -import { getLazyOsqueryAction, useIsOsqueryAvailableSimple } from './shared_components'; +import { + getLazyOsqueryAction, + getLazyLiveQueryField, + useIsOsqueryAvailableSimple, +} from './shared_components'; export class OsqueryPlugin implements Plugin { private kibanaVersion: string; @@ -94,8 +98,10 @@ export class OsqueryPlugin implements Plugin + // eslint-disable-next-line react/display-name + ({ + formMethods, + ...props + }: LiveQueryQueryFieldProps & { + formMethods: UseFormReturn<{ + label: string; + query: string; + ecs_mapping: Record; + }>; + }) => { + const LiveQueryField = lazy(() => import('../live_queries/form/live_query_query_field')); + + return ( + + + + + + + + ); + }; diff --git a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx index 5e158c51c02d10..ff464e7782bb78 100644 --- a/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx +++ b/x-pack/plugins/osquery/public/shared_components/lazy_osquery_action.tsx @@ -6,15 +6,20 @@ */ import React, { lazy, Suspense } from 'react'; +import ServicesWrapper from './services_wrapper'; +import type { ServicesWrapperProps } from './services_wrapper'; +import type { OsqueryActionProps } from './osquery_action'; -// @ts-expect-error update types -// eslint-disable-next-line react/display-name -export const getLazyOsqueryAction = (services) => (props) => { - const OsqueryAction = lazy(() => import('./osquery_action')); +export const getLazyOsqueryAction = + // eslint-disable-next-line react/display-name + (services: ServicesWrapperProps['services']) => (props: OsqueryActionProps) => { + const OsqueryAction = lazy(() => import('./osquery_action')); - return ( - - - - ); -}; + return ( + + + + + + ); + }; diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx index 15c6fa645de115..bc039b334a9104 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_action/index.tsx @@ -5,10 +5,9 @@ * 2.0. */ -import { EuiErrorBoundary, EuiLoadingContent, EuiEmptyPrompt, EuiCode } from '@elastic/eui'; +import { EuiLoadingContent, EuiEmptyPrompt, EuiCode } from '@elastic/eui'; import React, { useMemo } from 'react'; -import { QueryClientProvider } from '@tanstack/react-query'; -import type { CoreStart } from '@kbn/core/public'; + import { AGENT_STATUS_ERROR, EMPTY_PROMPT, @@ -16,17 +15,14 @@ import { PERMISSION_DENIED, SHORT_EMPTY_TITLE, } from './translations'; -import { KibanaContextProvider, useKibana } from '../../common/lib/kibana'; - +import { useKibana } from '../../common/lib/kibana'; import { LiveQuery } from '../../live_queries'; -import { queryClient } from '../../query_client'; import { OsqueryIcon } from '../../components/osquery_icon'; -import { KibanaThemeProvider } from '../../shared_imports'; import { useIsOsqueryAvailable } from './use_is_osquery_available'; -import type { StartPlugins } from '../../types'; -interface OsqueryActionProps { +export interface OsqueryActionProps { agentId?: string; + defaultValues?: {}; formType: 'steps' | 'simple'; hideAgentsField?: boolean; addToTimeline?: (payload: { query: [string, string]; isIcon?: true }) => React.ReactElement; @@ -35,6 +31,7 @@ interface OsqueryActionProps { const OsqueryActionComponent: React.FC = ({ agentId, formType = 'simple', + defaultValues, hideAgentsField, addToTimeline, }) => { @@ -54,7 +51,7 @@ const OsqueryActionComponent: React.FC = ({ const { osqueryAvailable, agentFetched, isLoading, policyFetched, policyLoading, agentData } = useIsOsqueryAvailable(agentId); - if (!agentId || (agentFetched && !agentData)) { + if (agentId && agentFetched && !agentData) { return emptyPrompt; } @@ -77,15 +74,15 @@ const OsqueryActionComponent: React.FC = ({ ); } - if (isLoading) { + if (agentId && isLoading) { return ; } - if (!policyFetched && policyLoading) { + if (agentId && !policyFetched && policyLoading) { return ; } - if (!osqueryAvailable) { + if (agentId && !osqueryAvailable) { return ( } @@ -96,7 +93,7 @@ const OsqueryActionComponent: React.FC = ({ ); } - if (agentData?.status !== 'online') { + if (agentId && agentData?.status !== 'online') { return ( } @@ -113,38 +110,14 @@ const OsqueryActionComponent: React.FC = ({ agentId={agentId} hideAgentsField={hideAgentsField} addToTimeline={addToTimeline} + {...defaultValues} /> ); }; -export const OsqueryAction = React.memo(OsqueryActionComponent); - -type OsqueryActionWrapperProps = { services: CoreStart & StartPlugins } & OsqueryActionProps; +OsqueryActionComponent.displayName = 'OsqueryAction'; -const OsqueryActionWrapperComponent: React.FC = ({ - services, - agentId, - formType, - hideAgentsField = false, - addToTimeline, -}) => ( - - - - - - - - - -); - -const OsqueryActionWrapper = React.memo(OsqueryActionWrapperComponent); +export const OsqueryAction = React.memo(OsqueryActionComponent); // eslint-disable-next-line import/no-default-export -export { OsqueryActionWrapper as default }; +export { OsqueryAction as default }; diff --git a/x-pack/plugins/osquery/public/shared_components/osquery_action/osquery_action.test.tsx b/x-pack/plugins/osquery/public/shared_components/osquery_action/osquery_action.test.tsx index 927d408884d202..ba56cfa0da62dc 100644 --- a/x-pack/plugins/osquery/public/shared_components/osquery_action/osquery_action.test.tsx +++ b/x-pack/plugins/osquery/public/shared_components/osquery_action/osquery_action.test.tsx @@ -81,13 +81,6 @@ describe('Osquery Action', () => { const { getByText } = renderWithContext(); expect(getByText(EMPTY_PROMPT)).toBeInTheDocument(); }); - it('should return empty prompt when no agentId', async () => { - spyOsquery(); - mockKibana(); - - const { getByText } = renderWithContext(); - expect(getByText(EMPTY_PROMPT)).toBeInTheDocument(); - }); it('should return permission denied when agentFetched and agentData available', async () => { spyOsquery({ agentData: {} }); mockKibana(); diff --git a/x-pack/plugins/osquery/public/shared_components/services_wrapper.tsx b/x-pack/plugins/osquery/public/shared_components/services_wrapper.tsx new file mode 100644 index 00000000000000..7b6949696bbeef --- /dev/null +++ b/x-pack/plugins/osquery/public/shared_components/services_wrapper.tsx @@ -0,0 +1,36 @@ +/* + * 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 { EuiErrorBoundary } from '@elastic/eui'; +import React from 'react'; +import { QueryClientProvider } from '@tanstack/react-query'; +import type { CoreStart } from '@kbn/core/public'; +import { KibanaContextProvider } from '../common/lib/kibana'; + +import { queryClient } from '../query_client'; +import { KibanaThemeProvider } from '../shared_imports'; +import type { StartPlugins } from '../types'; + +export interface ServicesWrapperProps { + services: CoreStart & StartPlugins; + children: React.ReactNode; +} + +const ServicesWrapperComponent: React.FC = ({ services, children }) => ( + + + + {children} + + + +); + +const ServicesWrapper = React.memo(ServicesWrapperComponent); + +// eslint-disable-next-line import/no-default-export +export { ServicesWrapper as default }; diff --git a/x-pack/plugins/osquery/public/types.ts b/x-pack/plugins/osquery/public/types.ts index 69c4befec1b6cc..c19dd10802f320 100644 --- a/x-pack/plugins/osquery/public/types.ts +++ b/x-pack/plugins/osquery/public/types.ts @@ -16,12 +16,13 @@ import type { TriggersAndActionsUIPublicPluginSetup, TriggersAndActionsUIPublicPluginStart, } from '@kbn/triggers-actions-ui-plugin/public'; -import type { getLazyOsqueryAction } from './shared_components'; +import type { getLazyLiveQueryField, getLazyOsqueryAction } from './shared_components'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface OsqueryPluginSetup {} export interface OsqueryPluginStart { OsqueryAction?: ReturnType; + LiveQueryField?: ReturnType; isOsqueryAvailable: (props: { agentId: string }) => boolean; } diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/investigation_guide_view.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/investigation_guide_view.tsx index 5148dde4d6b596..4e9ff49a2b1dd2 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/investigation_guide_view.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/investigation_guide_view.tsx @@ -7,10 +7,11 @@ import { EuiSpacer, EuiTitle, EuiText } from '@elastic/eui'; import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; - -import React, { useMemo } from 'react'; +import React, { createContext, useMemo } from 'react'; import styled from 'styled-components'; +import type { GetBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers'; +import { useBasicDataFromDetailsData } from '../../../timelines/components/side_panel/event_details/helpers'; import * as i18n from './translations'; import { useRuleWithFallback } from '../../../detections/containers/detection_engine/rules/use_rule_with_fallback'; import { MarkdownRenderer } from '../markdown_editor'; @@ -22,6 +23,8 @@ export const Indent = styled.div` word-break: break-word; `; +export const BasicAlertDataContext = createContext>({}); + const InvestigationGuideViewComponent: React.FC<{ data: TimelineEventsDetailsItem[]; }> = ({ data }) => { @@ -32,13 +35,14 @@ const InvestigationGuideViewComponent: React.FC<{ : item?.originalValue ?? null; }, [data]); const { rule: maybeRule } = useRuleWithFallback(ruleId); + const basicAlertData = useBasicDataFromDetailsData(data); if (!maybeRule?.note) { return null; } return ( - <> +
{i18n.INVESTIGATION_GUIDE}
@@ -51,7 +55,7 @@ const InvestigationGuideViewComponent: React.FC<{ - +
); }; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts index c7f8481c362470..494ecb0c6b4d0e 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/index.ts @@ -5,37 +5,27 @@ * 2.0. */ -import type { EuiLinkAnchorProps } from '@elastic/eui'; import { getDefaultEuiMarkdownParsingPlugins, getDefaultEuiMarkdownProcessingPlugins, getDefaultEuiMarkdownUiPlugins, } from '@elastic/eui'; -// Remove after this issue is resolved: https://github.com/elastic/eui/issues/4688 -import type { Options as Remark2RehypeOptions } from 'mdast-util-to-hast'; -import type { FunctionComponent } from 'react'; -import type rehype2react from 'rehype-react'; -import type { Plugin, PluggableList } from 'unified'; + import * as timelineMarkdownPlugin from './timeline'; +import * as osqueryMarkdownPlugin from './osquery'; export const { uiPlugins, parsingPlugins, processingPlugins } = { uiPlugins: getDefaultEuiMarkdownUiPlugins(), parsingPlugins: getDefaultEuiMarkdownParsingPlugins(), - processingPlugins: getDefaultEuiMarkdownProcessingPlugins() as [ - [Plugin, Remark2RehypeOptions], - [ - typeof rehype2react, - Parameters[0] & { - components: { a: FunctionComponent; timeline: unknown }; - } - ], - ...PluggableList - ], + processingPlugins: getDefaultEuiMarkdownProcessingPlugins(), }; uiPlugins.push(timelineMarkdownPlugin.plugin); +uiPlugins.push(osqueryMarkdownPlugin.plugin); parsingPlugins.push(timelineMarkdownPlugin.parser); +parsingPlugins.push(osqueryMarkdownPlugin.parser); // This line of code is TS-compatible and it will break if [1][1] change in the future. processingPlugins[1][1].components.timeline = timelineMarkdownPlugin.renderer; +processingPlugins[1][1].components.osquery = osqueryMarkdownPlugin.renderer; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx new file mode 100644 index 00000000000000..7b96f3886159c5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/index.tsx @@ -0,0 +1,273 @@ +/* + * 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 { pickBy, isEmpty } from 'lodash'; +import type { Plugin } from 'unified'; +import React, { useContext, useMemo, useState, useCallback } from 'react'; +import type { RemarkTokenizer } from '@elastic/eui'; +import { + EuiSpacer, + EuiCodeBlock, + EuiModalHeader, + EuiModalHeaderTitle, + EuiModalBody, + EuiModalFooter, + EuiButton, + EuiButtonEmpty, +} from '@elastic/eui'; +import { useForm, FormProvider } from 'react-hook-form'; +import styled from 'styled-components'; +import type { EuiMarkdownEditorUiPluginEditorProps } from '@elastic/eui/src/components/markdown_editor/markdown_types'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { useKibana } from '../../../../lib/kibana'; +import { LabelField } from './label_field'; +import OsqueryLogo from './osquery_icon/osquery.svg'; +import { OsqueryFlyout } from '../../../../../detections/components/osquery/osquery_flyout'; +import { BasicAlertDataContext } from '../../../event_details/investigation_guide_view'; +import { convertECSMappingToObject } from './utils'; + +const StyledEuiButton = styled(EuiButton)` + > span > img { + margin-block-end: 0; + } +`; + +const OsqueryEditorComponent = ({ + node, + onSave, + onCancel, +}: EuiMarkdownEditorUiPluginEditorProps<{ + configuration: { + label?: string; + query: string; + ecs_mapping: { [key: string]: {} }; + }; +}>) => { + const isEditMode = node != null; + const { osquery } = useKibana().services; + const formMethods = useForm<{ + label: string; + query: string; + ecs_mapping: Record; + }>({ + defaultValues: { + label: node?.configuration?.label, + query: node?.configuration?.query, + ecs_mapping: node?.configuration?.ecs_mapping, + }, + }); + + const onSubmit = useCallback( + (data) => { + onSave( + `!{osquery${JSON.stringify( + pickBy( + { + query: data.query, + label: data.label, + ecs_mapping: convertECSMappingToObject(data.ecs_mapping), + }, + (value) => !isEmpty(value) + ) + )}}`, + { + block: true, + } + ); + }, + [onSave] + ); + + const OsqueryActionForm = useMemo(() => { + if (osquery?.LiveQueryField) { + const { LiveQueryField } = osquery; + + return ( + + + + + + ); + } + return null; + }, [formMethods, osquery]); + + return ( + <> + + + {isEditMode ? ( + + ) : ( + + )} + + + + + <>{OsqueryActionForm} + + + + + {i18n.translate('xpack.securitySolution.markdown.osquery.modalCancelButtonLabel', { + defaultMessage: 'Cancel', + })} + + + {isEditMode ? ( + + ) : ( + + )} + + + + ); +}; + +const OsqueryEditor = React.memo(OsqueryEditorComponent); + +export const plugin = { + name: 'osquery', + button: { + label: 'Osquery', + iconType: 'logoOsquery', + }, + helpText: ( +
+ + {'!{osquery{options}}'} + + +
+ ), + editor: OsqueryEditor, +}; + +export const parser: Plugin = function () { + const Parser = this.Parser; + const tokenizers = Parser.prototype.blockTokenizers; + const methods = Parser.prototype.blockMethods; + + const tokenizeOsquery: RemarkTokenizer = function (eat, value, silent) { + if (value.startsWith('!{osquery') === false) return false; + + const nextChar = value[9]; + + if (nextChar !== '{' && nextChar !== '}') return false; // this isn't actually a osquery + + if (silent) { + return true; + } + + // is there a configuration? + const hasConfiguration = nextChar === '{'; + + let match = '!{osquery'; + let configuration = {}; + + if (hasConfiguration) { + let configurationString = ''; + + let openObjects = 0; + + for (let i = 9; i < value.length; i++) { + const char = value[i]; + if (char === '{') { + openObjects++; + configurationString += char; + } else if (char === '}') { + openObjects--; + if (openObjects === -1) { + break; + } + configurationString += char; + } else { + configurationString += char; + } + } + + match += configurationString; + try { + configuration = JSON.parse(configurationString); + } catch (e) { + const now = eat.now(); + this.file.fail(`Unable to parse osquery JSON configuration: ${e}`, { + line: now.line, + column: now.column + 9, + }); + } + } + + match += '}'; + + return eat(match)({ + type: 'osquery', + configuration, + }); + }; + + tokenizers.osquery = tokenizeOsquery; + methods.splice(methods.indexOf('text'), 0, 'osquery'); +}; + +// receives the configuration from the parser and renders +const RunOsqueryButtonRenderer = ({ + configuration, +}: { + configuration: { + label?: string; + query: string; + ecs_mapping: { [key: string]: {} }; + }; +}) => { + const [showFlyout, setShowFlyout] = useState(false); + const { agentId } = useContext(BasicAlertDataContext); + + const handleOpen = useCallback(() => setShowFlyout(true), [setShowFlyout]); + + const handleClose = useCallback(() => setShowFlyout(false), [setShowFlyout]); + + return ( + <> + + {configuration.label ?? + i18n.translate('xpack.securitySolution.markdown.osquery.runOsqueryButtonLabel', { + defaultMessage: 'Run Osquery', + })} + + {showFlyout && ( + + )} + + ); +}; + +export { RunOsqueryButtonRenderer as renderer }; diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/label_field.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/label_field.tsx new file mode 100644 index 00000000000000..3517bbf7643d30 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/label_field.tsx @@ -0,0 +1,49 @@ +/* + * 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, { useMemo } from 'react'; +import { useController } from 'react-hook-form'; +import { EuiFieldText, EuiFormRow } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +interface QueryDescriptionFieldProps { + euiFieldProps?: Record; +} + +const LabelFieldComponent = ({ euiFieldProps }: QueryDescriptionFieldProps) => { + const { + field: { onChange, value, name: fieldName }, + fieldState: { error }, + } = useController({ + name: 'label', + defaultValue: '', + }); + + const hasError = useMemo(() => !!error?.message, [error?.message]); + + return ( + + + + ); +}; + +export const LabelField = React.memo(LabelFieldComponent); diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/index.tsx b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/index.tsx new file mode 100644 index 00000000000000..fe7b811bd70fdc --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/index.tsx @@ -0,0 +1,19 @@ +/* + * 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 type { EuiIconProps } from '@elastic/eui'; +import { EuiIcon } from '@elastic/eui'; +import OsqueryLogo from './osquery.svg'; + +export type OsqueryIconProps = Omit; + +const OsqueryIconComponent: React.FC = (props) => ( + +); + +export const OsqueryIcon = React.memo(OsqueryIconComponent); diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/osquery.svg b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/osquery.svg new file mode 100755 index 00000000000000..32305a5916c042 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/osquery_icon/osquery.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/utils.ts b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/utils.ts new file mode 100644 index 00000000000000..77e2f14c514203 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/osquery/utils.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 { isEmpty, reduce } from 'lodash'; + +export const convertECSMappingToObject = ( + ecsMapping: Array<{ + key: string; + result: { + type: string; + value: string; + }; + }> +) => + reduce( + ecsMapping, + (acc, value) => { + if (!isEmpty(value?.key) && !isEmpty(value.result?.type) && !isEmpty(value.result?.value)) { + acc[value.key] = { + [value.result.type]: value.result.value, + }; + } + + return acc; + }, + {} as Record + ); diff --git a/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx b/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx index 126f057742901d..4999d757cd0479 100644 --- a/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/osquery/osquery_flyout.tsx @@ -25,16 +25,19 @@ const OsqueryActionWrapper = styled.div` `; export interface OsqueryFlyoutProps { - agentId: string; + agentId?: string; + defaultValues?: {}; onClose: () => void; } -const TimelineComponent = React.memo((props) => { - return ; -}); +const TimelineComponent = React.memo((props) => ); TimelineComponent.displayName = 'TimelineComponent'; -export const OsqueryFlyoutComponent: React.FC = ({ agentId, onClose }) => { +export const OsqueryFlyoutComponent: React.FC = ({ + agentId, + defaultValues, + onClose, +}) => { const { services: { osquery, timelines }, } = useKibana(); @@ -70,30 +73,38 @@ export const OsqueryFlyoutComponent: React.FC = ({ agentId, }, [getAddToTimelineButton] ); - // @ts-expect-error - const { OsqueryAction } = osquery; - return ( - - - -

{ACTION_OSQUERY}

-
-
- - - - - - - - -
- ); + + if (osquery?.OsqueryAction) { + return ( + + + +

{ACTION_OSQUERY}

+
+
+ + + + + + + + +
+ ); + } + + return null; }; export const OsqueryFlyout = React.memo(OsqueryFlyoutComponent); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx index b34338b4cbce96..065ac297ee468b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/helpers.tsx @@ -11,8 +11,9 @@ import type { TimelineEventsDetailsItem } from '../../../../../common/search_str import { getFieldValue } from '../../../../detections/components/host_isolation/helpers'; import { DEFAULT_ALERTS_INDEX, DEFAULT_PREVIEW_INDEX } from '../../../../../common/constants'; -interface GetBasicDataFromDetailsData { +export interface GetBasicDataFromDetailsData { alertId: string; + agentId?: string; isAlert: boolean; hostName: string; ruleName: string; @@ -31,6 +32,11 @@ export const useBasicDataFromDetailsData = ( const alertId = useMemo(() => getFieldValue({ category: '_id', field: '_id' }, data), [data]); + const agentId = useMemo( + () => getFieldValue({ category: 'agent', field: 'agent.id' }, data), + [data] + ); + const hostName = useMemo( () => getFieldValue({ category: 'host', field: 'host.name' }, data), [data] @@ -44,17 +50,18 @@ export const useBasicDataFromDetailsData = ( return useMemo( () => ({ alertId, + agentId, isAlert, hostName, ruleName, timestamp, }), - [alertId, hostName, isAlert, ruleName, timestamp] + [agentId, alertId, hostName, isAlert, ruleName, timestamp] ); }; /* -The referenced alert _index in the flyout uses the `.internal.` such as +The referenced alert _index in the flyout uses the `.internal.` such as `.internal.alerts-security.alerts-spaceId` in the alert page flyout and .internal.preview.alerts-security.alerts-spaceId` in the rule creation preview flyout but we always want to use their respective aliase indices rather than accessing their backing .internal. indices. From 87f6a28b6747c2839af167d4e0bd12db8eaab08e Mon Sep 17 00:00:00 2001 From: Irina Truong Date: Sun, 11 Sep 2022 14:04:22 -0700 Subject: [PATCH 046/144] [8.5] Pipeline definitions for ML inference (#140233) * Started working on ML pipeline definitions for https://github.com/elastic/enterprise-search-team/issues/2650. * Call ml from ElasticsearchClient. * Remove TODOs. * Fix linter errors. * Fix linter error. * Fix test. * Formatting. * Comment. * Handle edge cases: model not found, or has no input fiels. * Apply suggestions from code review Co-authored-by: Brian McGue * Review feedback. Co-authored-by: Brian McGue --- .../utils/create_pipeline_definitions.test.ts | 161 ++++++++++++++++++ .../utils/create_pipeline_definitions.ts | 66 +++++++ 2 files changed, 227 insertions(+) diff --git a/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.test.ts b/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.test.ts index 27208dbaed00e5..6961086edac1be 100644 --- a/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.test.ts +++ b/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.test.ts @@ -8,6 +8,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { createIndexPipelineDefinitions } from './create_pipeline_definitions'; +import { formatMlPipelineBody } from './create_pipeline_definitions'; describe('createIndexPipelineDefinitions util function', () => { const indexName = 'my-index'; @@ -34,3 +35,163 @@ describe('createIndexPipelineDefinitions util function', () => { expect(mockClient.ingest.putPipeline).toHaveBeenCalledTimes(3); }); }); + +describe('formatMlPipelineBody util function', () => { + const modelId = 'my-model-id'; + let modelInputField = 'my-model-input-field'; + const modelType = 'my-model-type'; + const modelVersion = 3; + const sourceField = 'my-source-field'; + const destField = 'my-dest-field'; + + const mockClient = { + ml: { + getTrainedModels: jest.fn(), + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return the pipeline body', async () => { + const expectedResult = { + description: '', + version: 1, + processors: [ + { + remove: { + field: `ml.inference.${destField}`, + ignore_missing: true, + }, + }, + { + inference: { + model_id: modelId, + target_field: `ml.inference.${destField}`, + field_map: { + sourceField: modelInputField, + }, + }, + }, + { + append: { + field: '_source._ingest.processors', + value: [ + { + type: modelType, + model_id: modelId, + model_version: modelVersion, + processed_timestamp: '{{{ _ingest.timestamp }}}', + }, + ], + }, + }, + ], + }; + + const mockResponse = { + count: 1, + trained_model_configs: [ + { + model_id: modelId, + version: modelVersion, + model_type: modelType, + input: { field_names: [modelInputField] }, + }, + ], + }; + mockClient.ml.getTrainedModels.mockImplementation(() => Promise.resolve(mockResponse)); + const actualResult = await formatMlPipelineBody( + modelId, + sourceField, + destField, + mockClient as unknown as ElasticsearchClient + ); + expect(actualResult).toEqual(expectedResult); + expect(mockClient.ml.getTrainedModels).toHaveBeenCalledTimes(1); + }); + + it('should raise an error if no model found', async () => { + const mockResponse = { + error: { + root_cause: [ + { + type: 'resource_not_found_exception', + reason: 'No known trained model with model_id [my-model-id]', + }, + ], + type: 'resource_not_found_exception', + reason: 'No known trained model with model_id [my-model-id]', + }, + status: 404, + }; + mockClient.ml.getTrainedModels.mockImplementation(() => Promise.resolve(mockResponse)); + const asyncCall = formatMlPipelineBody( + modelId, + sourceField, + destField, + mockClient as unknown as ElasticsearchClient + ); + await expect(asyncCall).rejects.toThrow(Error); + expect(mockClient.ml.getTrainedModels).toHaveBeenCalledTimes(1); + }); + + it('should insert a placeholder if model has no input fields', async () => { + modelInputField = 'MODEL_INPUT_FIELD'; + const expectedResult = { + description: '', + version: 1, + processors: [ + { + remove: { + field: `ml.inference.${destField}`, + ignore_missing: true, + }, + }, + { + inference: { + model_id: modelId, + target_field: `ml.inference.${destField}`, + field_map: { + sourceField: modelInputField, + }, + }, + }, + { + append: { + field: '_source._ingest.processors', + value: [ + { + type: modelType, + model_id: modelId, + model_version: modelVersion, + processed_timestamp: '{{{ _ingest.timestamp }}}', + }, + ], + }, + }, + ], + }; + const mockResponse = { + count: 1, + trained_model_configs: [ + { + model_id: modelId, + version: modelVersion, + model_type: modelType, + input: { field_names: [] }, + }, + ], + }; + mockClient.ml.getTrainedModels.mockImplementation(() => Promise.resolve(mockResponse)); + const actualResult = await formatMlPipelineBody( + modelId, + sourceField, + destField, + mockClient as unknown as ElasticsearchClient + ); + expect(actualResult).toEqual(expectedResult); + expect(mockClient.ml.getTrainedModels).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.ts b/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.ts index 377f12fd632087..666588dd098869 100644 --- a/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.ts +++ b/x-pack/plugins/enterprise_search/server/utils/create_pipeline_definitions.ts @@ -5,12 +5,17 @@ * 2.0. */ +import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core/server'; export interface CreatedPipelines { created: string[]; } +export interface MlInferencePipeline extends IngestPipeline { + version?: number; +} + /** * Used to create index-specific Ingest Pipelines to be used in conjunction with Enterprise Search * ingestion mechanisms. Three pipelines are created: @@ -225,3 +230,64 @@ export const createIndexPipelineDefinitions = ( }); return { created: [indexName, `${indexName}@custom`, `${indexName}@ml-inference`] }; }; + +/** + * Format the body of an ML inference pipeline for a specified model. + * Does not create the pipeline, only returns JSON for the user to preview. + * @param modelId modelId selected by user. + * @param sourceField The document field that model will read. + * @param destinationField The document field that the model will write to. + * @param esClient the Elasticsearch Client to use when retrieving model details. + */ +export const formatMlPipelineBody = async ( + modelId: string, + sourceField: string, + destinationField: string, + esClient: ElasticsearchClient +): Promise => { + const models = await esClient.ml.getTrainedModels({ model_id: modelId }); + // if we didn't find this model, we can't return anything useful + if (models.trained_model_configs === undefined || models.trained_model_configs.length === 0) { + throw new Error(`Couldn't find any trained models with id [${modelId}]`); + } + const model = models.trained_model_configs[0]; + // if model returned no input field, insert a placeholder + const modelInputField = + model.input?.field_names?.length > 0 ? model.input.field_names[0] : 'MODEL_INPUT_FIELD'; + const modelType = model.model_type; + const modelVersion = model.version; + return { + description: '', + version: 1, + processors: [ + { + remove: { + field: `ml.inference.${destinationField}`, + ignore_missing: true, + }, + }, + { + inference: { + model_id: modelId, + target_field: `ml.inference.${destinationField}`, + field_map: { + sourceField: modelInputField, + }, + }, + }, + { + append: { + field: '_source._ingest.processors', + value: [ + { + type: modelType, + model_id: modelId, + model_version: modelVersion, + processed_timestamp: '{{{ _ingest.timestamp }}}', + }, + ], + }, + }, + ], + }; +}; From 6ad09d6684ae6136d72dc496cb64ac26b096e08e Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Sun, 11 Sep 2022 22:40:30 -0600 Subject: [PATCH 047/144] [api-docs] Daily api_docs build (#140465) --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/core.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- api_docs/kbn_alerts.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- .../kbn_core_injected_metadata_browser.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...core_saved_objects_api_server_internal.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_internal.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_get_repo_files.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- ...hared_ux_button_exit_full_screen_mocks.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_package_json.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_type_summarizer.mdx | 2 +- api_docs/kbn_type_summarizer_core.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/osquery.devdocs.json | 22 ++++++++++++++++++- api_docs/osquery.mdx | 4 ++-- api_docs/plugin_directory.mdx | 6 ++--- api_docs/presentation_util.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_field_list.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 383 files changed, 406 insertions(+), 386 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 3025e3c667a605..e89fd0e7ed367d 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index a9f6922f31c0d9..a6de0eddd53d61 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 877f5f0d599125..db20b98ed0f6a5 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 969deada62d833..d46ff5aa181b59 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 031ff7c280dc6f..371251c3d2f6bc 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index e02969f5caba7a..48441c7541f204 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index d6497fb8300dc6..051acd0e759002 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index f02bf545e8e1c1..a0952458e0f453 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index e383d536d3839d..dbd163dff3005e 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 8a9e27d98094a4..94a6853c57cce2 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index c5c83271b18d3a..67f888cd10fab7 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index fb001228fa3f46..2d93e7b6a7ef6c 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index b9047f4a24a4a9..885e264937e68f 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 6da5ee9f0746da..07fbe27b7c0486 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 204d2415d2b7e7..9d6e7827173248 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 8cd3ce3704b80e..604f24762a12bc 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 1c7d146485765c..454aa521d59424 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index aae133a2412204..125f6303237f39 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index c211da19b2a495..bb06789a9d338b 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index ade7e083d84bc6..e862a2588c40d4 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index f6c931e4cec1a2..247b776e53e307 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 6744db8e790c79..594122e246d100 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 224ac3dfcb2dd8..2881eb78d6fbdb 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index d5d199ff46ba19..fe964392680cd0 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 9b05096958466d..35957ede2cc4fb 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 24fee647eeb7f8..63c9c3051d4e40 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 0e9744507654c6..d9ba036f7bbe64 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index a350a7959739ab..07f70de66a166b 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 5ebeeae4c53dc7..4a9e44b189a791 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 7b8f1654a1d64f..6ab2af56de8a69 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 1d250c38c549c4..c21e6fc7a14bd0 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index d12e6c092ab7db..844946af12dba9 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index f382a16c0f09f6..6d0f630e840481 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index a2e50f21c7e264..cf1334edf5db33 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index b1d1432f6b4c7a..31c161302239c3 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index ecde934e30affb..337602bc8deb6e 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 976cd3fddd0976..88767bde098f93 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index b9ce5e25248335..bfb01ed547536b 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index b914b0c80cf12d..67fc800a393f54 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 8a494564e676a5..55e41dee84df05 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 4e9ab427950b2e..272f14fa331c1b 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index e4fe738d7d291e..883e69752d7c20 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index c71511b96c318e..2fd851509964a8 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 33ba87eb7b5f3f..dd3e3a7c1b9c4b 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 3bfd49a0a0ab52..ec3bd2846e1a8a 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index f1d49dc44f8ddd..323af21664b16a 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index b6d68cb2b323e8..ce8b70c802891c 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index c6b1df89b1360d..44d11e482c8992 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index b2e2ad2f8444ef..170818628b752f 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index c150b5f41465fc..ba84f73e3531a0 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index 28f009516b4190..a1190ad13be1af 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index 56897b6597827a..e58dcecd23eb3d 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 5a8e3138f08124..be939038342854 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index e038774bfa9374..7084d5dd8614b8 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 92e0207fbd8be6..a3a2ffc66d7248 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 60ec7732acd75f..5acb5094dcbe3f 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index a6d8d632ff9b01..d2657f32584525 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index c53e062e643a8a..deb8f6162875b1 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 5ed82a919fcd6c..3318c54d6b6f92 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 5bbe2b58a1accd..ad5da6eb527158 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 0a59397f0c068a..a566a62d1f8467 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 81c79814547423..5285ccf5319123 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 4920906b8fcdd5..96c41a5268b4d9 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 9c5867adf2e443..28ccaee3ae731b 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index e75e271da43f16..e2601319591a4e 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index a86d6e9cba7a55..1e719609801988 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 757980d3e6c938..f55d67c1fc3dc1 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 0b69c7a96e6c4d..89439f8a35a2a4 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 7f5fa0c4a8cd78..132c55a0f53208 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 2b5a1eed6ec3f7..023dcb2b4bb369 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index ec2a36eb92df78..e491c482cb629a 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index f75dae8740f9a4..c4ba600af1dab3 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index d4a81f43dc82f7..bb77b10ad5c557 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 429b53bdf7e101..1aa6719c6e3135 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 4c4cb3cf3efa2b..180b6a7699ad30 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index f1e62abb86ab14..4b863396dbcf42 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 4e062859cb0b1c..01a492a721e05d 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index a7a506ce86fc25..14b01e3c7be4af 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 6b570ab3aab8c2..a129e1b408e447 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 0cfd4d21feb792..dc390f25f01709 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index fc833e10f26853..741443fe91e356 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index e26a00304d9a0f..40098db9d607fd 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index cf6f7a950ad551..4d457a94dff83f 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index eb21786d914dde..75ad6cf16351d1 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 01f5e595c9dd38..988bba727b23c1 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 52bc3424f9e013..f308239b6d4757 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 79413342ab401f..0714ab8c48ebf3 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index a85abe0d1f4629..1cd0b626f5510a 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 91991ec18f8845..7777a057c28945 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 473131110b37d5..b85fd73d4c9016 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 5109686b45e4b6..8937453ad90ef5 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 94e10b46f2316c..21d0c98603bd59 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index bc0f9edc666711..5bf553a6b4e27e 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index ba57a73b999421..84e37926b9d2ef 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 3fa4da5936b38a..08601a43abe024 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 51c111c7988f76..42e241da77343c 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 1b76d387f45098..5600e432ddde88 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index f6e23ad2b383cf..36b74b926858bc 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 07637ebdaf7c01..53392790ff3213 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index d35d7443a193eb..4596828c8a7f73 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 34e28daec02d0d..8c56c35df8037b 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index c739147712e761..e369bc6cf95739 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index 0461dd4be981f0..a02516d41e635c 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 2e725a63445363..4cf9fbbbd4890a 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index 430137c8d9959d..ed7cb4116ff68c 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index fce198d30b8a7d..d6275075f4f2d4 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 083977d68e52fc..8b8b3352b3e036 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index 80d56506102423..26b3493760d23c 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 6ac42a81cccaa5..6aeec78a9de0b6 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index d81872b86ed9fa..cb3d85753a695b 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 74d33cc2a26e24..3f5b097166b70d 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 6a273e0bbc6400..c3308a653104f3 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index 2dc2bbdec82d5d..b77b28d64156f4 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 2cfda1b1e14f51..a4c4c5108d54ec 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 26aee3b1d9481b..6d190e7921922b 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index daf442ebc26b46..adcb25e4e3b654 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 7a1c650f01e582..a2fc67402f23ee 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index c1d20b550cd001..125a8ddb62eb20 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 3af31403f23ace..490c09706c8aaa 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 9b92df3210b123..8507ca2cb39034 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index b1ef52b7dc5e7a..9aa393700f1cc5 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index b7cebd8cb78697..64475b318c5063 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index d5a72fb8c9f7a2..3b16e74a4edd20 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index d8e28509d3f6df..19bafc1b112daf 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index a20a4f29e62352..2afd793f95c198 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index dbc1a29005b263..7e71e344bbf24e 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 64faca1523441a..36cab5deb51a26 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index a8866f07127b85..1a6af787887d5b 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 2cb03493086ef5..ca61b99d2dbab3 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index e806ee84139e5a..177fc4c26f4ae4 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 2de4c4665618d2..4200bb38465ccd 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 7e486b492cb7fb..b95726bae4f8c2 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 0c29cdee5039d0..96baa43f4f803f 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index fabbeb65d0a485..9d90489b193a27 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index c977778112ccb0..dc43d1ef8ebe29 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index c8454f5f4a1ad7..72d95cc2173bbb 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index f90f61f3441829..2604bdf1307f6e 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index 644f37bab4f8bf..a70c8ebdd20389 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 73c5b5e7ab616e..090d7dea7fc90c 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 90a1d70ad8ebe3..062468ef28b456 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 41fa8208a1d3d2..13666c7455aa72 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 07e62ce040beec..8f122bb2f056e3 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 0e1f4bc4292dd1..7bf289e5bff954 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 9c661db0a0d4c4..d5afd2459cb6a7 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index fdffc72c5de1c6..643fc21c88e998 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index adcf42480843ba..337c83d0c71edd 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index f99d83106c9ba3..41b228a7827286 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 00f2319d95a4d9..23037163144c57 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 2036346943a3bc..13949e3052dc57 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 2430f7709e3f2e..35d1ab22608d64 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index e9e57ae24900b6..0145a71c0d7b2d 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 193a70ee06f5ce..87346ec4fa5b72 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 4d4bde98c08249..d9ba50274fda17 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 6b8cf748eea9ba..90e86fc55e65bb 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index b470dc449dd954..60f31535742b48 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 23ce8cc600f0e9..302e26129c7121 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index fa7a24d11ac1fe..337f272c28fe55 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index f137c3dccec8a7..8d4b519f59c142 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 8911ce825c3480..196c31459d3f23 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index f4f423d7181cb2..730e06acc610b0 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index a99659d4c5b9fb..11c953906f0dcc 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index d0ea7ef6101557..a5ba2bcf8c3cc2 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 239347724a16b2..75f3667db69e4b 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 38f9308d189240..ace513c8f3fd69 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index c4091bcd35f9b6..ee9a394184d4e5 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 7e34262d8bb258..5333d41e145846 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 4ae04538bb07ee..4a89b92fff036d 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 7ceeca5e39b67a..14247d429667c7 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 8b580261d449ba..0e8f65ff9da071 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 5de3e5441f0a3a..52483dfa4dc6ca 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index c9a8a6fa296fb4..857037bab1093b 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index e21ba36217cdb8..b2767486e65926 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 24be1762c920d3..6afb7d61f7327e 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index a441e2ef32789a..23ae70cfd0c9f0 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 8a5919dd59d977..7a3a3d003792fb 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index b838876f7f7476..23db97bef04a91 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index bfcbeb55a18b88..f7574d68fb4aa8 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 66abe1a3927010..fb970d77d9a9ba 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index 904a4b379dcf10..71eb12db08bbce 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 1fc8fea5658dec..d84f5c5c73c7e4 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 4db9b280efd7af..93ab71cd6d0c2b 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index bf1cb01f73a28b..089cea7cbcd40c 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 1afe62c5c2ce8f..ac8a36714f9c95 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 70950894bcedc0..afa0e5688428de 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index 59dc76b98636e3..fbecff8bedc447 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 5892c9fb0a0167..56315c20f6063a 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index c407dcb5e295a7..ae5b78204d1b8a 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index dc9525f01b09b8..0b3f8c2f078bcc 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index 2ce5252fd39dfa..e2f35211ba038f 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index 2ffdb6dc3ce24f..c13d91d1c3d3b5 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 2b67fbdd407222..6e430a5fa2611c 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index e3395e86dae43d..06e6a2ecbe2789 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index bbff1bf85dbbd1..f6aecda23d6f1f 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 396a6320edec5b..5fac3e3216d8af 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index e538113de3fac6..1743916cfc8258 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 58ed0073a4cd91..f815aa153ef383 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 36d33ea9b1a749..30a90ae7a976ab 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 687cebf362c2ad..1b1bcdac498dd2 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index 0c8d201b108db7..d2a4f74edd929c 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 01b7c9b7547267..7fecf1916746cb 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index 2c23d98be0d556..794d64d7e64e92 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index ae8a3bb99e2318..f0d5725c883fa5 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index f66d8b9d925c2c..65edbdba1a628d 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index 60daee6a7d7e5a..d9f583d515cfcc 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index 6a9cf22463b094..925ad46a926100 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index cbf6d686988729..10165c0389dd68 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index 400a2273ebb48f..fed0b546122cdb 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index a580f88ebdfe1a..07324152643719 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 74de25b9936b3c..5052cc57dc19ef 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 45af778aabb7a0..79a90a07cb0131 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index cc570f84b5efa6..60c5375cd230d2 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 189fd0164bfe1b..34d1cab6fdcee2 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 436322f7854287..cc0de7274d49f8 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 7a5442a1a0cae5..59692fd76e3269 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index e9fa94182c598e..b29893225438dc 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index 3218754cc239cc..a95ffcdf1e28b2 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 010511da8532e1..5daa6d13cf6a3d 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index d9e2807bff8938..e76afe4af60ff3 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index cd39f7f26935e5..0fde4b55f119ed 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 3b1835f359eb85..2644e4c3b5e711 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 597ccfe2be00e2..beefe799a31bf0 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 1604ebb3ec2e37..59951f466f8312 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 1bf6e2f7f5a006..cce2805a4412c3 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index e24c7591af75bf..db4ae2018ca5bf 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 4215f85c6f8c53..28ee9c2cff91cf 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index c9bfd3ca76b144..136a0dd3d55f07 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index ba1864c2dc58d2..eb5455dd7d830a 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 645ca3d359c8bb..40b7ac766e87ac 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index ddd1905cc7047b..57561b5cbc50f2 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 99dd8ebca16535..d2c265790b9b41 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index d9efa7441aa9b6..2bf014a652c69a 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 936f1dee9f1e43..c2c4c4d0337a88 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 05349d6c8ba5cc..4049be82b4dfbd 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 529512b81500c2..306996d8dcc166 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index ec7d13bd2af088..e7387cd969effc 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index fa531348925610..dbc89d69930c2d 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index d72524950d40e0..943a7e8f6ee378 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index c30d18c57d28f6..42d8da1b6627e2 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 088b7c3ab3e51e..dca53916d65b63 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 3b262cbc1a1e84..6ba7fb075d16d4 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index d0805d8f0e3a7f..2832f3e8dae4b7 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 49721d1cea988a..9860f169230158 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 1156a351ae27f0..aff7a4c3270b2e 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index f96c7fb58804f0..a162aa944dc67f 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 306793a3ad5578..875e36a1a99915 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index fb0f0be2270ffe..9a84263750a9f5 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 7591ffa38ef80d..c7162db39b87cc 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 322849b06d34f2..8b0c2dce899c42 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index c9b0d4fe6a0ac9..eff3e884b3bd79 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 668f0851dbfa57..3fdf23cd53c02e 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index bd11c64056cf7c..37bb135d5c2809 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index cd76e179c4559d..a5383cbc3b5303 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 2e09a5e871c858..ba7590ffbe159d 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 415a5ae710a72d..017f82899a8377 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 9807368001ea3b..49f9e90702310b 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 2db12aca59f5e5..ebe0a2779fedf0 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 8857544c0305a4..15d8fcc4196eec 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index d9498bc90ca629..a3eb896fea4c66 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index 9d7b8f7633c3b8..db43ecbf5d1907 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 8670181ea26180..3fa0a82da7e870 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index dae3809a97f6e0..90ed9b37626b4e 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 45dc38e5c6942c..43dbe59c8b4417 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index e5f1b8291164bd..79e9918ff415aa 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 8f20caaeb9cae1..4260459c9d0644 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 8344e032aad540..d7da0dc87559bd 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index f1bf9b41313027..93b46261b29ac2 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index ade345bb5615dd..73955118e002c4 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index 447ee7b71c7e2d..e0d4fb5f40c7da 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index 5c71c74ae942c0..ce83347c99d760 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 10400f212cfcf4..aaee03632d3bd2 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 0fee8a03fa8703..72c05e4c8e5973 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index f0b51e26b5ad69..5396d1d529cc3f 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index 2609283ac184eb..ebeb4c6b525a95 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 08fc2716208596..af5b4f23845c26 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 81c4323ef5b3ff..6fbaa004f2aa15 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index c6b4f08bec31a8..216b4ec105498a 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index f827d296d95f7b..86b17203dd3aae 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 76fa4162e4659a..ba2a281401304a 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index e6532bbf960c50..fc4bed4b1a0013 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 52ccc629f932ca..d0c9c5ed9392b5 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 34dac5295a708c..f6aa153d98fd14 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 21df75d4ceec4e..967834391e6dc3 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 5cf068205b142f..527b5039281e57 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 9975f552e2d184..b132757f0b152a 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index fd907ad4acd667..92be11cf2c6b62 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 8f006ae13ac7fd..579464a3146de8 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index ae83d0e7fe3b7a..c89f5a58f576e7 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 9e345e8fb66ff2..f7430ec4cffc92 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index d60e9ac96d2803..770abdeea3c3d8 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 96cc446e6fefb6..f20bc874aa489a 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 24567ffdf3445b..c88c99fdfa8e13 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index 46ecfc817267f2..ad038875cef839 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 8af04a8805463c..008ba2f53e93cb 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 0150f05323bba3..7883d6366d4f37 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index c6fa1e5cc264db..c7fe9875c57c67 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index fae6e16ab92a53..bc834ee2ff41a2 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 8e8ab3618f788b..1dd32b08c95c52 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index faf5cee741994d..a76ec2f91fad05 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 8751ba41cac845..ffd690fb8d542c 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 2e430f9d0266d8..6d4cee2cf48e51 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 17572df2363419..bb0e1cfdac9b08 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 6d6d8317f0e551..bbfa64010e3ba2 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index f4d7dd3e0f4e15..762df9d42c29c4 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 8c5ef3203612dd..957ed8febfcaee 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index 078368ad360139..98103fbb8df504 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index df03b17c3ae0f7..ff85afae240ef1 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 9e9f1254c74611..9e427901caff1a 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index cce7fbc5689fd3..6900408be11c01 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 594491fdecc8bd..cd577edea97f4e 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index 36d9451444b3e7..cbe25e33be5094 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 4feba3b38f7593..e2a850694866ba 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index a157a01b3c9a6b..e09f9577b2b034 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index a97469db4181d7..a789dd35533620 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index e1be4466c01de9..8af7864ea49398 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 50f5703693a3de..cb45d6c5a44311 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 52b62a9bc69a49..0de39481f86298 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 25d86a53be826d..1652626d9f56f8 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 573d944ceebb59..6e43b6db2c76be 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index fc72f81f23e7b0..48955617613a98 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 01d17ee704f7cc..8c8b8e8c9ef660 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index b0c5f348b512bc..1f36b3105cdc87 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 9e0b6900d20978..a726ebc34c5fb9 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 157780cd018b86..74513f78d1f369 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 3319ee23629ef4..a5fb71bb58e91d 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index e9978c6653cb9c..7cac92107a18cb 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index c3fb959fdf6b5d..616e1e5a07fc76 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 07fad65fc3b271..afe72ce3daf472 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index bb16b57ac9e244..c2674d018305b2 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index fd9c6c30b99a1d..ac8837b6ca8945 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index c788ba9e7f6231..ba58d7518c6e45 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index db53834bfe1342..c580985bc8887d 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.devdocs.json b/api_docs/osquery.devdocs.json index f217e15c771ef0..8d45fc77730ef9 100644 --- a/api_docs/osquery.devdocs.json +++ b/api_docs/osquery.devdocs.json @@ -40,7 +40,27 @@ "label": "OsqueryAction", "description": [], "signature": [ - "((props: any) => JSX.Element) | undefined" + "((props: ", + "OsqueryActionProps", + ") => JSX.Element) | undefined" + ], + "path": "x-pack/plugins/osquery/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "osquery", + "id": "def-public.OsqueryPluginStart.LiveQueryField", + "type": "Function", + "tags": [], + "label": "LiveQueryField", + "description": [], + "signature": [ + "(({ formMethods, ...props }: ", + "LiveQueryQueryFieldProps", + " & { formMethods: ", + "UseFormReturn", + "<{ label: string; query: string; ecs_mapping: Record; }, any>; }) => JSX.Element) | undefined" ], "path": "x-pack/plugins/osquery/public/types.ts", "deprecated": false, diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 07b26fd92d2b6f..1e938d796a4a71 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Security asset management](https://github.com/orgs/elastic/teams/securi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 13 | 0 | 13 | 0 | +| 14 | 0 | 14 | 2 | ## Client diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index c12a7b23b50daa..40d73b16b018a6 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 30721 | 180 | 20533 | 969 | +| 30722 | 180 | 20534 | 971 | ## Plugin Directory @@ -114,7 +114,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 34 | 0 | 34 | 2 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | | | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 397 | 2 | 394 | 30 | -| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 13 | 0 | 13 | 0 | +| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 14 | 0 | 14 | 2 | | painlessLab | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 243 | 2 | 187 | 12 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 4 | 0 | 4 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index e8fcd477b4023f..ecf895a3e0f7a0 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index c2adbf5d4b6884..9d61b29944ba92 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index ec9abe0f75103c..286139d6fe63f3 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index b36bcf7dcf04d7..3a26281e749b68 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index fcb98184ac721a..c9236042b14f04 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 2d29a830ac2107..d04909af548968 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 54366ae393ceb9..03f4861574ec82 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 01b865e133a773..312293e55cc627 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index ed0eb8d662405f..e629a877e6a51a 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index c26048db692895..456808d926a824 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index e3f02c8e029885..8dc7f9e54649e1 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index a6487b37023814..15f259f2794d48 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 4a39fa9cdd5619..5c308f8c268e95 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 74ba599fc51b36..47f80ea4bfb327 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 81eee14edb1fb7..e1d55dd7b8f5e7 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index dad1dd94bbd4dc..29a07610f1e5c5 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 22fac81e890237..9c8e4190bf491c 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 07e5942620fc3e..6bd52414173b99 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index a775f63cffd49e..1e59aff6842ba3 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index ec94eb7b7ec89f..02b72e1835c090 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 4124b573463298..85ade27d7ba7e5 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 3bc27698a60367..696dc5d8713357 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 66be10fc270cd1..3a62678f11769d 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 75102dbc52f82c..30f763ba4488f5 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index c848059af41e09..f56b57fe0398c4 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 2d383534e6173a..80abde5c72bc85 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 3f6612eeb70903..8e620fcd483210 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 601adbcdf93833..020d59da436aa6 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 55b6299dfd4779..27facd7cbc7910 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index e69614e09b29e6..6b6af45f6d599c 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 603903b5e16845..68f0239219c7a6 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index f82809f791062d..f9e3c5956fea5c 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index a44e9ef13c884b..82043a2029661c 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index a03b99f1f280b6..5b3a5638c74ef1 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 46cbdd7c383542..bebe8e757136a4 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index e4353912664717..ba4d70200d7143 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index 514bfd452f0c4a..eac1395483f264 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 5e0571a91b3bed..ac07b7b6dec90d 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 88ceeaf9a67b0d..27386a94c37aa3 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index b4590576a445e8..c25eb47e0fbdc8 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 688644059d558d..492e3f940e9909 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index e683cc9d59d0cc..bd06921b3a7404 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 65bd5ac3f83eb1..32a53d10810cc3 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 569b354b761a6b..1a0fe74391504c 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 362e6fa9159ff0..faaeaad6e7c4b7 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index de331861fc09e2..9892ae39456836 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index 197508c600b5c2..d2862d4828d210 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index e4d1de0d28a318..8c22d419a997cf 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 72cff108cef000..eb856d91fcbba0 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-09-11 +date: 2022-09-12 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 6a2fa9f4b43576e8c44e12b657440eebdb7e5d11 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Mon, 12 Sep 2022 10:13:36 +0200 Subject: [PATCH 048/144] [ML] Explain Log Rate Spikes: Improve streaming headers for certain proxy configs. (#139637) Updates response headers to make response streaming work with certain proxy configurations. --- .../ml/aiops_utils/src/stream_factory.test.ts | 30 ++++++++++++++++--- .../ml/aiops_utils/src/stream_factory.ts | 17 ++++++----- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts b/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts index a0c5212244ad6e..1e6d7b40b22d05 100644 --- a/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts +++ b/x-pack/packages/ml/aiops_utils/src/stream_factory.test.ts @@ -44,7 +44,12 @@ describe('streamFactory', () => { streamResult += chunk.toString('utf8'); } - expect(responseWithHeaders.headers).toBe(undefined); + expect(responseWithHeaders.headers).toStrictEqual({ + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + 'Transfer-Encoding': 'chunked', + 'X-Accel-Buffering': 'no', + }); expect(streamResult).toBe('push1push2'); }); @@ -65,7 +70,12 @@ describe('streamFactory', () => { const parsedItems = streamItems.map((d) => JSON.parse(d)); - expect(responseWithHeaders.headers).toBe(undefined); + expect(responseWithHeaders.headers).toStrictEqual({ + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + 'Transfer-Encoding': 'chunked', + 'X-Accel-Buffering': 'no', + }); expect(parsedItems).toHaveLength(2); expect(parsedItems[0]).toStrictEqual(mockItem1); expect(parsedItems[1]).toStrictEqual(mockItem2); @@ -105,7 +115,13 @@ describe('streamFactory', () => { const streamResult = decoded.toString('utf8'); - expect(responseWithHeaders.headers).toStrictEqual({ 'content-encoding': 'gzip' }); + expect(responseWithHeaders.headers).toStrictEqual({ + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + 'content-encoding': 'gzip', + 'Transfer-Encoding': 'chunked', + 'X-Accel-Buffering': 'no', + }); expect(streamResult).toBe('push1push2'); done(); @@ -143,7 +159,13 @@ describe('streamFactory', () => { const parsedItems = streamItems.map((d) => JSON.parse(d)); - expect(responseWithHeaders.headers).toStrictEqual({ 'content-encoding': 'gzip' }); + expect(responseWithHeaders.headers).toStrictEqual({ + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + 'content-encoding': 'gzip', + 'Transfer-Encoding': 'chunked', + 'X-Accel-Buffering': 'no', + }); expect(parsedItems).toHaveLength(2); expect(parsedItems[0]).toStrictEqual(mockItem1); expect(parsedItems[1]).toStrictEqual(mockItem2); diff --git a/x-pack/packages/ml/aiops_utils/src/stream_factory.ts b/x-pack/packages/ml/aiops_utils/src/stream_factory.ts index 9df9702eb08707..7d685369e4d10e 100644 --- a/x-pack/packages/ml/aiops_utils/src/stream_factory.ts +++ b/x-pack/packages/ml/aiops_utils/src/stream_factory.ts @@ -106,13 +106,16 @@ export function streamFactory( const responseWithHeaders: StreamFactoryReturnType['responseWithHeaders'] = { body: stream, - ...(isCompressed - ? { - headers: { - 'content-encoding': 'gzip', - }, - } - : {}), + headers: { + ...(isCompressed ? { 'content-encoding': 'gzip' } : {}), + + // This disables response buffering on proxy servers (Nginx, uwsgi, fastcgi, etc.) + // Otherwise, those proxies buffer responses up to 4/8 KiB. + 'X-Accel-Buffering': 'no', + 'Cache-Control': 'no-cache', + Connection: 'keep-alive', + 'Transfer-Encoding': 'chunked', + }, }; return { DELIMITER, end, push, responseWithHeaders }; From 6380e4cecb5be96e7475c5d9a1cdc6a5054234a6 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Mon, 12 Sep 2022 11:01:00 +0200 Subject: [PATCH 049/144] [Discover] Fix flaky test regarding field actions in a flyout (#140415) * [Discover] Fix flaky test regarding field actions in a flyout * [Discover] Update a11y tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + .../doc_viewer_table/table_cell_actions.tsx | 6 ++---- test/accessibility/apps/discover.ts | 12 ++++++++++-- test/functional/apps/context/_filters.ts | 13 ++++++++----- .../discover/group2/_data_grid_doc_navigation.ts | 4 +--- .../apps/discover/group2/_data_grid_doc_table.ts | 6 ++---- test/functional/services/data_grid.ts | 11 +++++++++++ 7 files changed, 35 insertions(+), 18 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ebc25aadd21ac8..cb9690ca3dc8d7 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -13,6 +13,7 @@ /src/plugins/saved_search/ @elastic/kibana-data-discovery /x-pack/plugins/discover_enhanced/ @elastic/kibana-data-discovery /test/functional/apps/discover/ @elastic/kibana-data-discovery +/test/functional/apps/context/ @elastic/kibana-data-discovery /test/api_integration/apis/unified_field_list/ @elastic/kibana-data-discovery /x-pack/plugins/graph/ @elastic/kibana-data-discovery /x-pack/test/functional/apps/graph @elastic/kibana-data-discovery diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx index d67e12cf8eccc1..9f29f3ba7f69f0 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx +++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_table/table_cell_actions.tsx @@ -177,15 +177,13 @@ export const TableActions = ({ }, ]; - const testSubject = `openFieldActionsButton-${field}`; - if (mode === 'inline') { return ( {panels[0].items.map((item) => ( @@ -210,7 +208,7 @@ export const TableActions = ({ { await PageObjects.discover.clickDocViewerTab(0); - await testSubjects.click('openFieldActionsButton-Cancelled'); + if (await testSubjects.exists('openFieldActionsButton-Cancelled')) { + await testSubjects.click('openFieldActionsButton-Cancelled'); + } else { + await testSubjects.existOrFail('fieldActionsGroup-Cancelled'); + } await a11y.testAppSnapshot(); }); it('a11y test for data-grid table with columns', async () => { await testSubjects.click('toggleColumnButton-Cancelled'); - await testSubjects.click('openFieldActionsButton-Carrier'); + if (await testSubjects.exists('openFieldActionsButton-Carrier')) { + await testSubjects.click('openFieldActionsButton-Carrier'); + } else { + await testSubjects.existOrFail('fieldActionsGroup-Carrier'); + } await testSubjects.click('toggleColumnButton-Carrier'); await testSubjects.click('euiFlyoutCloseButton'); await toasts.dismissAllToasts(); diff --git a/test/functional/apps/context/_filters.ts b/test/functional/apps/context/_filters.ts index 8c77d4fd013c19..f9e95080c92e4b 100644 --- a/test/functional/apps/context/_filters.ts +++ b/test/functional/apps/context/_filters.ts @@ -18,7 +18,6 @@ const TEST_COLUMN_NAMES = ['extension', 'geo.src']; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dataGrid = getService('dataGrid'); const filterBar = getService('filterBar'); - const testSubjects = getService('testSubjects'); const retry = getService('retry'); const browser = getService('browser'); @@ -34,12 +33,17 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('inclusive filter should be addable via expanded data grid rows', async function () { await retry.waitFor(`filter ${TEST_ANCHOR_FILTER_FIELD} in filterbar`, async () => { await dataGrid.clickRowToggle({ isAnchorRow: true, renderMoreRows: true }); - await testSubjects.click(`openFieldActionsButton-${TEST_ANCHOR_FILTER_FIELD}`); - await testSubjects.click(`addFilterForValueButton-${TEST_ANCHOR_FILTER_FIELD}`); + await dataGrid.clickFieldActionInFlyout( + TEST_ANCHOR_FILTER_FIELD, + 'addFilterForValueButton' + ); await PageObjects.context.waitUntilContextLoadingHasFinished(); return await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, TEST_ANCHOR_FILTER_VALUE, true); }); + + await dataGrid.closeFlyout(); + await retry.waitFor(`filter matching docs in data grid`, async () => { const fields = await dataGrid.getFields(); return fields @@ -71,8 +75,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('filter for presence should be addable via expanded data grid rows', async function () { await retry.waitFor('an exists filter in the filterbar', async () => { await dataGrid.clickRowToggle({ isAnchorRow: true, renderMoreRows: true }); - await testSubjects.click(`openFieldActionsButton-${TEST_ANCHOR_FILTER_FIELD}`); - await testSubjects.click(`addExistsFilterButton-${TEST_ANCHOR_FILTER_FIELD}`); + await dataGrid.clickFieldActionInFlyout(TEST_ANCHOR_FILTER_FIELD, 'addExistsFilterButton'); await PageObjects.context.waitUntilContextLoadingHasFinished(); return await filterBar.hasFilter(TEST_ANCHOR_FILTER_FIELD, 'exists', true); }); diff --git a/test/functional/apps/discover/group2/_data_grid_doc_navigation.ts b/test/functional/apps/discover/group2/_data_grid_doc_navigation.ts index 6ea883f7a560dc..2041d5fe500fc7 100644 --- a/test/functional/apps/discover/group2/_data_grid_doc_navigation.ts +++ b/test/functional/apps/discover/group2/_data_grid_doc_navigation.ts @@ -60,9 +60,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.discover.waitUntilSearchingHasFinished(); await dataGrid.clickRowToggle({ rowIndex: 0 }); - - await testSubjects.click('openFieldActionsButton-@timestamp'); - await testSubjects.click('addExistsFilterButton-@timestamp'); + await dataGrid.clickFieldActionInFlyout('@timestamp', 'addExistsFilterButton'); const hasExistsFilter = await filterBar.hasFilter('@timestamp', 'exists', true, false, false); expect(hasExistsFilter).to.be(true); diff --git a/test/functional/apps/discover/group2/_data_grid_doc_table.ts b/test/functional/apps/discover/group2/_data_grid_doc_table.ts index c2f55847e7d1ee..a90932595d42a6 100644 --- a/test/functional/apps/discover/group2/_data_grid_doc_table.ts +++ b/test/functional/apps/discover/group2/_data_grid_doc_table.ts @@ -197,8 +197,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // add columns const fields = ['_id', '_index', 'agent']; for (const field of fields) { - await testSubjects.click(`openFieldActionsButton-${field}`); - await testSubjects.click(`toggleColumnButton-${field}`); + await dataGrid.clickFieldActionInFlyout(field, 'toggleColumnButton'); } const headerWithFields = await dataGrid.getHeaderFields(); @@ -206,8 +205,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // remove columns for (const field of fields) { - await testSubjects.click(`openFieldActionsButton-${field}`); - await testSubjects.click(`toggleColumnButton-${field}`); + await dataGrid.clickFieldActionInFlyout(field, 'toggleColumnButton'); } const headerWithoutFields = await dataGrid.getHeaderFields(); diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index fbd4310489fef2..614a7764230796 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -312,6 +312,17 @@ export class DataGridService extends FtrService { return await tableDocViewRow.findByTestSubject(`~removeInclusiveFilterButton`); } + public async clickFieldActionInFlyout(fieldName: string, actionName: string): Promise { + const openPopoverButtonSelector = `openFieldActionsButton-${fieldName}`; + const inlineButtonsGroupSelector = `fieldActionsGroup-${fieldName}`; + if (await this.testSubjects.exists(openPopoverButtonSelector)) { + await this.testSubjects.click(openPopoverButtonSelector); + } else { + await this.testSubjects.existOrFail(inlineButtonsGroupSelector); + } + await this.testSubjects.click(`${actionName}-${fieldName}`); + } + public async removeInclusiveFilter( detailsRow: WebElementWrapper, fieldName: string From 757ddcbbad801f21e966f8b0084902fd69fc44a2 Mon Sep 17 00:00:00 2001 From: Oleg Sucharevich Date: Mon, 12 Sep 2022 12:20:41 +0300 Subject: [PATCH 050/144] [Cloud Posture] feat: add additional auth with EKS cluster (#140272) --- .../components/fleet_extensions/eks_form.tsx | 28 +++++++++++++++++-- .../components/fleet_extensions/mocks.ts | 9 ++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_form.tsx index 2de87bdb660f7c..7cf3fb779942cb 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_form.tsx @@ -23,14 +23,35 @@ export const eksVars = [ id: 'secret_access_key', label: i18n.translate( 'xpack.csp.createPackagePolicy.eksIntegrationSettingsSection.secretAccessKeyFieldLabel', - { defaultMessage: 'Secret access key' } + { defaultMessage: 'Secret Access Key' } ), }, { id: 'session_token', label: i18n.translate( 'xpack.csp.createPackagePolicy.eksIntegrationSettingsSection.sessionTokenFieldLabel', - { defaultMessage: 'Session token' } + { defaultMessage: 'Session Token' } + ), + }, + { + id: 'shared_credential_file', + label: i18n.translate( + 'xpack.csp.createPackagePolicy.eksIntegrationSettingsSection.sharedCredentialsFileFieldLabel', + { defaultMessage: 'Shared Credential File' } + ), + }, + { + id: 'credential_profile_name', + label: i18n.translate( + 'xpack.csp.createPackagePolicy.eksIntegrationSettingsSection.sharedCredentialFileFieldLabel', + { defaultMessage: 'Credential Profile Name' } + ), + }, + { + id: 'role_arn', + label: i18n.translate( + 'xpack.csp.createPackagePolicy.eksIntegrationSettingsSection.roleARNFieldLabel', + { defaultMessage: 'ARN Role' } ), }, ] as const; @@ -50,6 +71,9 @@ const getEksVars = (input?: NewPackagePolicyInput): EksFormVars => { access_key_id: vars?.access_key_id.value || '', secret_access_key: vars?.secret_access_key.value || '', session_token: vars?.session_token.value || '', + shared_credential_file: vars?.shared_credential_file.value || '', + credential_profile_name: vars?.credential_profile_name.value || '', + role_arn: vars?.role_arn.value || '', }; }; diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts index 2af55809f1c913..05be275af41c04 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/mocks.ts @@ -51,6 +51,15 @@ export const getCspNewPolicyMock = (type: BenchmarkId = 'cis_k8s'): NewPackagePo session_token: { type: 'text', }, + shared_credential_file: { + type: 'text', + }, + credential_profile_name: { + type: 'text', + }, + role_arn: { + type: 'text', + }, }, }, ], From c80de819640040870e50348bdab8a04bb3fea61b Mon Sep 17 00:00:00 2001 From: Dmitry Tomashevich <39378793+dimaanj@users.noreply.github.com> Date: Mon, 12 Sep 2022 12:58:16 +0300 Subject: [PATCH 051/144] [Discover] Fix saved search embeddable rendering (#140264) * [Discover] fix rendering issue * [Discover] add functional test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/embeddable/saved_search_embeddable.tsx | 2 ++ .../embeddable/_saved_search_embeddable.ts | 10 ++++++++++ test/functional/services/data_grid.ts | 15 ++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx index f76343156c9554..00cbd0a2ffcb0f 100644 --- a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx +++ b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx @@ -484,6 +484,8 @@ export class SavedSearchEmbeddable ReactDOM.unmountComponentAtNode(this.node); } this.node = domNode; + + this.renderReactComponent(this.node, this.searchProps!); } private renderReactComponent(domNode: HTMLElement, searchProps: SearchProps) { diff --git a/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts b/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts index 08a0296ad8c083..bd47c072e77359 100644 --- a/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts +++ b/test/functional/apps/discover/embeddable/_saved_search_embeddable.ts @@ -77,5 +77,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dataGrid.checkCurrentRowsPerPageToBe(10); }); + + it('should render duplicate saved search embeddables', async () => { + await PageObjects.dashboard.switchToEditMode(); + await addSearchEmbeddableToDashboard(); + const [firstGridCell, secondGridCell] = await dataGrid.getAllCellElements(); + const firstGridCellContent = await firstGridCell.getVisibleText(); + const secondGridCellContent = await secondGridCell.getVisibleText(); + + expect(firstGridCellContent).to.be.equal(secondGridCellContent); + }); }); } diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index 614a7764230796..68b2553478df7e 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -80,15 +80,24 @@ export class DataGridService extends FtrService { .map((cell) => $(cell).text()); } + private getCellElementSelector(rowIndex: number = 0, columnIndex: number = 0) { + return `[data-test-subj="euiDataGridBody"] [data-test-subj="dataGridRowCell"][data-gridcell-column-index="${columnIndex}"][data-gridcell-row-index="${rowIndex}"]`; + } + /** * Returns a grid cell element by row & column indexes. * @param rowIndex data row index starting from 0 (0 means 1st row) * @param columnIndex column index starting from 0 (0 means 1st column) */ public async getCellElement(rowIndex: number = 0, columnIndex: number = 0) { - return await this.find.byCssSelector( - `[data-test-subj="euiDataGridBody"] [data-test-subj="dataGridRowCell"][data-gridcell-column-index="${columnIndex}"][data-gridcell-row-index="${rowIndex}"]` - ); + return await this.find.byCssSelector(this.getCellElementSelector(rowIndex, columnIndex)); + } + + /** + * The same as getCellElement, but useful when multiple data grids are on the page. + */ + public async getAllCellElements(rowIndex: number = 0, columnIndex: number = 0) { + return await this.find.allByCssSelector(this.getCellElementSelector(rowIndex, columnIndex)); } public async getDocCount(): Promise { From 591a9b11b08664846801c6b1e33fcf164c7b8741 Mon Sep 17 00:00:00 2001 From: Luke Gmys Date: Mon, 12 Sep 2022 12:22:22 +0200 Subject: [PATCH 052/144] [TIP] Add threat generation script for benchmarking and dev purposes (#140193) --- x-pack/plugins/threat_intelligence/README.md | 14 +- .../scripts/generate_indicators.js | 121 ++++++++++++++++++ 2 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/threat_intelligence/scripts/generate_indicators.js diff --git a/x-pack/plugins/threat_intelligence/README.md b/x-pack/plugins/threat_intelligence/README.md index 8c9c690924218a..945ab9b85a4f1f 100755 --- a/x-pack/plugins/threat_intelligence/README.md +++ b/x-pack/plugins/threat_intelligence/README.md @@ -19,7 +19,7 @@ Verify your node version [here](https://github.com/elastic/kibana/blob/main/.nod **Run Kibana:** > **Important:** -> +> > See here to get your `kibana.yaml` to enable the Threat Intelligence plugin. ``` @@ -27,6 +27,16 @@ yarn kbn reset && yarn kbn bootstrap yarn start --no-base-path ``` +### Performance + +You can generate large volumes of threat indicators on demand with the following script: + +``` +node scripts/generate_indicators.js +``` + +see the file in order to adjust the amount of indicators generated. The default is one million. + ### Useful hints Export local instance data to es_archives (will be loaded in cypress tests). @@ -45,4 +55,4 @@ See [CONTRIBUTING.md](https://github.com/elastic/kibana/blob/main/x-pack/plugins ## Issues -Please report any issues in [this GitHub project](https://github.com/orgs/elastic/projects/758/). \ No newline at end of file +Please report any issues in [this GitHub project](https://github.com/orgs/elastic/projects/758/). diff --git a/x-pack/plugins/threat_intelligence/scripts/generate_indicators.js b/x-pack/plugins/threat_intelligence/scripts/generate_indicators.js new file mode 100644 index 00000000000000..bade9615b630d7 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/scripts/generate_indicators.js @@ -0,0 +1,121 @@ +/* + * 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. + */ + +const { Client } = require('@elastic/elasticsearch'); +const faker = require('faker'); + +const THREAT_INDEX = 'ti-logs'; + +/** Drop the index first? */ +const CLEANUP_FIRST = true; + +/** Adjust this to alter the threat number */ +const HOW_MANY_THREATS = 1_000_000; + +/** Feed names */ +const FEED_NAMES = ['Max', 'Philippe', 'Lukasz', 'Fernanda', 'Drew']; + +/** + * Customizing this is optional, you can skip it + */ +const CHUNK_SIZE = 10_000; +const TO_GENERATE = HOW_MANY_THREATS; + +const client = new Client({ + node: 'http://localhost:9200', + auth: { + username: 'elastic', + password: 'changeme', + }, +}); + +const main = async () => { + if (await client.indices.exists({ index: THREAT_INDEX })) { + if (CLEANUP_FIRST) { + console.log(`deleting index "${THREAT_INDEX}"`); + + await client.indices.delete({ index: THREAT_INDEX }); + + await client.indices.create({ + index: THREAT_INDEX, + mappings: { + properties: { + 'threat.indicator.type': { + type: 'keyword', + }, + 'threat.feed.name': { + type: 'keyword', + }, + 'threat.indicator.url.original': { + type: 'keyword', + }, + 'threat.indicator.first_seen': { + type: 'date', + }, + '@timestamp': { + type: 'date', + }, + }, + }, + }); + } else { + console.info( + `!!! appending to existing index "${THREAT_INDEX}" !!! (because CLEANUP_FIRST is set to true)` + ); + } + } else if (!CLEANUP_FIRST) { + throw new Error( + `index "${THREAT_INDEX}" does not exist. run this script with CLEANUP_FIRST set to true or create it some other way first.` + ); + } + + let pendingCount = TO_GENERATE; + + // When there are threats to generate + while (pendingCount) { + const operations = []; + + for (let i = 0; i < CHUNK_SIZE; i++) { + const RANDOM_OFFSET_WITHIN_ONE_MONTH = Math.floor(Math.random() * 3600 * 24 * 30 * 1000); + + const timestamp = Date.now() - RANDOM_OFFSET_WITHIN_ONE_MONTH; + + operations.push( + ...[ + { create: { _index: THREAT_INDEX } }, + { + '@timestamp': timestamp, + 'threat.indicator.first_seen': timestamp, + 'threat.feed.name': FEED_NAMES[Math.ceil(Math.random() * FEED_NAMES.length) - 1], + 'threat.indicator.type': 'url', + 'threat.indicator.url.original': faker.internet.url(), + 'event.type': 'indicator', + 'event.category': 'threat', + }, + ] + ); + + pendingCount--; + + if (!pendingCount) { + break; + } + } + + await client.bulk({ operations }); + + console.info( + `${operations.length / 2} new threats indexed, ${ + pendingCount ? `${pendingCount} pending` : 'complete' + }` + ); + } + + console.info('done, run your tests would you?'); +}; + +main(); From 31f337db34e8d290a68992da1d4d73c18230c43a Mon Sep 17 00:00:00 2001 From: Marta Bondyra <4283304+mbondyra@users.noreply.github.com> Date: Mon, 12 Sep 2022 13:07:27 +0200 Subject: [PATCH 053/144] [Lens] Use query input for annotations (#140418) * refactor filter query * use new FilterQueryInput * open automagically when coming from manual annotations * fix range to query colors and labels --- .../dimension_panel/filtering.tsx | 121 +-------------- .../dimension_panel/time_shift.tsx | 8 - .../shared_components/filter_query_input.tsx | 143 ++++++++++++++++++ .../lens/public/shared_components/index.ts | 1 + .../annotations_panel.tsx | 53 ++++--- .../query_annotation_panel.tsx | 43 ++---- 6 files changed, 202 insertions(+), 167 deletions(-) create mode 100644 x-pack/plugins/lens/public/shared_components/filter_query_input.tsx diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx index 1c68844079fa63..059170d9702d86 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/filtering.tsx @@ -4,35 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { useState, useCallback } from 'react'; -import { i18n } from '@kbn/i18n'; +import React, { useCallback } from 'react'; import { isEqual } from 'lodash'; -import { - EuiLink, - EuiPanel, - EuiPopover, - EuiFormRow, - EuiFlexItem, - EuiFlexGroup, - EuiPopoverProps, - EuiIconTip, -} from '@elastic/eui'; import type { Query } from '@kbn/es-query'; import { GenericIndexPatternColumn, operationDefinitionMap } from '../operations'; import type { IndexPatternLayer } from '../types'; -import { QueryInput, useDebouncedValue, validateQuery } from '../../shared_components'; +import { validateQuery, FilterQueryInput } from '../../shared_components'; import type { IndexPattern } from '../../types'; -const filterByLabel = i18n.translate('xpack.lens.indexPattern.filterBy.label', { - defaultMessage: 'Filter by', -}); - -// to do: get the language from uiSettings -export const defaultFilter: Query = { - query: '', - language: 'kuery', -}; - export function setFilter(columnId: string, layer: IndexPatternLayer, query: Query | undefined) { return { ...layer, @@ -71,18 +50,6 @@ export function Filtering({ }, [columnId, indexPattern, inputFilter, layer, updateLayer] ); - const { inputValue: queryInput, handleInputChange: setQueryInput } = useDebouncedValue({ - value: inputFilter ?? defaultFilter, - onChange, - }); - const [filterPopoverOpen, setFilterPopoverOpen] = useState(false); - - const onClosePopup: EuiPopoverProps['closePopover'] = useCallback(() => { - setFilterPopoverOpen(false); - if (inputFilter) { - setQueryInput(inputFilter); - } - }, [inputFilter, setQueryInput]); const selectedOperation = operationDefinitionMap[selectedColumn.operationType]; @@ -90,84 +57,12 @@ export function Filtering({ return null; } - const { isValid: isInputFilterValid } = validateQuery(inputFilter, indexPattern); - const { isValid: isQueryInputValid, error: queryInputError } = validateQuery( - queryInput, - indexPattern - ); - - const labelNode = helpMessage ? ( - <> - {filterByLabel}{' '} - - - ) : ( - filterByLabel - ); - return ( - - - - - - {/* Empty for spacing */} - - { - setFilterPopoverOpen(!filterPopoverOpen); - }} - color={isInputFilterValid ? 'text' : 'danger'} - title={i18n.translate('xpack.lens.indexPattern.filterBy.clickToEdit', { - defaultMessage: 'Click to edit', - })} - > - {inputFilter?.query || - i18n.translate('xpack.lens.indexPattern.filterBy.emptyFilterQuery', { - defaultMessage: '(empty)', - })} - - - - - } - > - - {}} - /> - - - - - + ); } diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx index 930864091c2eb8..63696a3a2196c1 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/time_shift.tsx @@ -9,8 +9,6 @@ import { EuiFormRow, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; import { EuiComboBox } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useEffect, useState } from 'react'; - -import type { Query } from '@kbn/es-query'; import { DatatableUtilitiesService, parseTimeShift } from '@kbn/data-plugin/common'; import { adjustTimeScaleLabelSuffix, @@ -26,12 +24,6 @@ import { } from '../time_shift_utils'; import type { IndexPattern } from '../../types'; -// to do: get the language from uiSettings -export const defaultFilter: Query = { - query: '', - language: 'kuery', -}; - export function setTimeShift( columnId: string, layer: IndexPatternLayer, diff --git a/x-pack/plugins/lens/public/shared_components/filter_query_input.tsx b/x-pack/plugins/lens/public/shared_components/filter_query_input.tsx new file mode 100644 index 00000000000000..db585f5f282048 --- /dev/null +++ b/x-pack/plugins/lens/public/shared_components/filter_query_input.tsx @@ -0,0 +1,143 @@ +/* + * 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, { useCallback, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiLink, + EuiPanel, + EuiPopover, + EuiFormRow, + EuiFlexItem, + EuiFlexGroup, + EuiIconTip, + EuiPopoverProps, +} from '@elastic/eui'; +import type { Query } from '@kbn/es-query'; +import { QueryInput, useDebouncedValue, validateQuery } from '.'; +import type { IndexPattern } from '../types'; + +const filterByLabel = i18n.translate('xpack.lens.indexPattern.filterBy.label', { + defaultMessage: 'Filter by', +}); + +// to do: get the language from uiSettings +export const defaultFilter: Query = { + query: '', + language: 'kuery', +}; + +export function FilterQueryInput({ + inputFilter, + onChange, + indexPattern, + helpMessage, + label = filterByLabel, + initiallyOpen, +}: { + inputFilter: Query | undefined; + onChange: (query: Query) => void; + indexPattern: IndexPattern; + helpMessage?: string | null; + label?: string; + initiallyOpen?: boolean; +}) { + const [filterPopoverOpen, setFilterPopoverOpen] = useState(Boolean(initiallyOpen)); + const { inputValue: queryInput, handleInputChange: setQueryInput } = useDebouncedValue({ + value: inputFilter ?? defaultFilter, + onChange, + }); + + const onClosePopup: EuiPopoverProps['closePopover'] = useCallback(() => { + setFilterPopoverOpen(false); + }, []); + + const { isValid: isInputFilterValid } = validateQuery(inputFilter, indexPattern); + const { isValid: isQueryInputValid, error: queryInputError } = validateQuery( + queryInput, + indexPattern + ); + + return ( + + {label}{' '} + + + ) : ( + label + ) + } + fullWidth + isInvalid={!isInputFilterValid} + > + + + + + {/* Empty for spacing */} + + { + setFilterPopoverOpen(!filterPopoverOpen); + }} + color={isInputFilterValid ? 'text' : 'danger'} + title={i18n.translate('xpack.lens.indexPattern.filterBy.clickToEdit', { + defaultMessage: 'Click to edit', + })} + > + {inputFilter?.query || + i18n.translate('xpack.lens.indexPattern.filterBy.emptyFilterQuery', { + defaultMessage: '(empty)', + })} + + + + + } + > + + {}} + /> + + + + + + ); +} diff --git a/x-pack/plugins/lens/public/shared_components/index.ts b/x-pack/plugins/lens/public/shared_components/index.ts index 924f678c1f96b5..3f30eb64ff2c93 100644 --- a/x-pack/plugins/lens/public/shared_components/index.ts +++ b/x-pack/plugins/lens/public/shared_components/index.ts @@ -36,5 +36,6 @@ export { NameInput } from './name_input'; export { ValueLabelsSettings } from './value_labels_settings'; export { AxisTitleSettings } from './axis_title_settings'; export { DimensionEditorSection } from './dimension_section'; +export { FilterQueryInput } from './filter_query_input'; export * from './static_header'; export * from './vis_label'; diff --git a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx index 778a1a13e200e0..5d68e29a88d080 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/xy_config_panel/annotations_config_panel/annotations_panel.tsx @@ -6,7 +6,7 @@ */ import './index.scss'; -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiFormRow, EuiSwitch, EuiSwitchEvent, EuiButtonGroup, EuiSpacer } from '@elastic/eui'; import type { PaletteRegistry } from '@kbn/coloring'; @@ -31,7 +31,7 @@ import { useDebouncedValue, } from '../../../../shared_components'; import { isHorizontalChart } from '../../state_helpers'; -import { defaultAnnotationLabel } from '../../annotations/helpers'; +import { defaultAnnotationLabel, defaultRangeAnnotationLabel } from '../../annotations/helpers'; import { ColorPicker } from '../color_picker'; import { IconSelectSetting, TextDecorationSetting } from '../shared/marker_decoration_settings'; import { LineStyleSettings } from '../shared/line_style_settings'; @@ -42,7 +42,7 @@ import type { State, XYState, XYAnnotationLayerConfig } from '../../types'; import { ConfigPanelManualAnnotation } from './manual_annotation_panel'; import { ConfigPanelQueryAnnotation } from './query_annotation_panel'; import { TooltipSection } from './tooltip_annotation_panel'; -import { sanitizeProperties } from './helpers'; +import { sanitizeProperties, toLineAnnotationColor } from './helpers'; export const AnnotationsPanel = ( props: VisualizationDimensionEditorProps & { @@ -68,6 +68,14 @@ export const AnnotationsPanel = ( const isQueryBased = isQueryAnnotationConfig(currentAnnotation); const isRange = isRangeAnnotationConfig(currentAnnotation); + const [queryInputShouldOpen, setQueryInputShouldOpen] = React.useState(false); + useEffect(() => { + if (isQueryBased) { + setQueryInputShouldOpen(false); + } else { + setQueryInputShouldOpen(true); + } + }, [isQueryBased]); const setAnnotations = useCallback( (annotation) => { @@ -114,11 +122,11 @@ export const AnnotationsPanel = ( buttonSize="compressed" options={[ { - id: `lens_xyChart_annotation_staticDate`, - label: i18n.translate('xpack.lens.xyChart.annotation.staticDate', { + id: `lens_xyChart_annotation_manual`, + label: i18n.translate('xpack.lens.xyChart.annotation.manual', { defaultMessage: 'Static Date', }), - 'data-test-subj': 'lnsXY_annotation_staticDate', + 'data-test-subj': 'lnsXY_annotation_manual', }, { id: `lens_xyChart_annotation_query`, @@ -128,18 +136,28 @@ export const AnnotationsPanel = ( 'data-test-subj': 'lnsXY_annotation_query', }, ]} - idSelected={`lens_xyChart_annotation_${ - currentAnnotation?.type === 'query' ? 'query' : 'staticDate' - }`} + idSelected={`lens_xyChart_annotation_${currentAnnotation?.type}`} onChange={(id) => { - setAnnotations({ - type: id === `lens_xyChart_annotation_query` ? 'query' : 'manual', - // when switching to query, reset the key value - key: - !isQueryBased && id === `lens_xyChart_annotation_query` - ? { type: 'point_in_time' } - : currentAnnotation?.key, - }); + const typeFromId = id.replace('lens_xyChart_annotation_', ''); + if (currentAnnotation?.type === typeFromId) { + return; + } + if (currentAnnotation?.key.type === 'range') { + setAnnotations({ + type: typeFromId, + label: + currentAnnotation.label === defaultRangeAnnotationLabel + ? defaultAnnotationLabel + : currentAnnotation.label, + color: toLineAnnotationColor(currentAnnotation.color), + key: { type: 'point_in_time' }, + }); + } else { + setAnnotations({ + type: typeFromId, + key: currentAnnotation?.key, + }); + } }} isFullWidth /> @@ -151,6 +169,7 @@ export const AnnotationsPanel = ( frame={frame} state={state} layer={localLayer} + queryInputShouldOpen={queryInputShouldOpen} /> ) : ( | undefined) => void; frame: FramePublicAPI; state: XYState; layer: XYAnnotationLayerConfig; + queryInputShouldOpen?: boolean; }) => { - const inputQuery = annotation?.filter ?? defaultQuery; const currentIndexPattern = frame.dataViews.indexPatterns[layer.indexPatternId]; const currentExistingFields = frame.dataViews.existingFields[currentIndexPattern.title]; // list only supported field by operation, remove the rest @@ -58,51 +58,36 @@ export const ConfigPanelQueryAnnotation = ({ 'data-test-subj': `lns-fieldOption-${field.name}`, } as FieldOption; }); - const { isValid: isQueryInputValid, error: queryInputError } = validateQuery( - annotation?.filter, - currentIndexPattern - ); const selectedField = annotation?.timeField || currentIndexPattern.timeFieldName || options[0]?.value.field; const fieldIsValid = selectedField ? Boolean(currentIndexPattern.getFieldByName(selectedField)) : true; + return ( <> - { + onChange({ filter: { type: 'kibana_query', ...query } }); }} - disableAutoFocus - indexPatternTitle={frame.dataViews.indexPatterns[layer.indexPatternId].title} - isInvalid={!isQueryInputValid || inputQuery.query === ''} - onSubmit={() => {}} - data-test-subj="annotation-query-based-query-input" - placeholder={ - inputQuery.language === 'kuery' - ? i18n.translate('xpack.lens.annotations.query.queryPlaceholderKql', { - defaultMessage: '{example}', - values: { example: 'method : "GET"' }, - }) - : i18n.translate('xpack.lens.annotations.query.queryPlaceholderLucene', { - defaultMessage: '{example}', - values: { example: 'method:GET' }, - }) - } + indexPattern={currentIndexPattern} /> + Date: Mon, 12 Sep 2022 07:37:03 -0400 Subject: [PATCH 054/144] [ResponseOps][Cases] User assignment (#140208) * [ResponseOps][Cases] Assign users on cases sidebar section (#138108) * Add reusable user profile selector component * Refactoring services, auth * Adding suggest api and tests * Move to package and add examples * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Working integration tests * Switching suggest api tags * Adding assignees field * Adding tests for size and owner * Add server side example * CI Fixes * Adding assignee integration tests * fix tests * Addd tests * Starting user actions changes * Adding api tag tests * Addressing feedback * Using lodash for array comparison logic and tests * Fixing type error * Create suggest query * Adding assignees user action * [ResponseOps][Cases] Refactoring client args and authentication (#137345) * Refactoring services, auth * Fixing type errors * Adding assignees migration and tests * Fixing types and added more tests * Fixing cypress test * Fixing test * Add tests * Add security as dependency and fix types * Add bulk get profiles query * Rename folder * Addressed suggestions from code review * Fix types * Adding migration for assignees field and tests * Adding comments and a few more tests * Updating comments and spelling * Revert security solution optional * PR feedback * Updated user avatar component * Reduce size * Make security required * Fix tests * Addressing feedback * Do not retry suggestions * Assign users to a case * Restructure components * Move assignees to case view * Show assigned users * Refactoring bulk get and display name * Adding tests for user tooltip * Adding tests * Hovering and tests * Fixing errors * Some pr clean up * Fixing tests and adding more * Adding functional tests * Fixing jest test failure * Passing in current user profile * Refactoring assignment with useEffect * Fixing icon alignment and removal render bug * Fixing type errors * Fixing test errors * Adding bulk get privs and tests * Fixing popover tests * Handling unknown users * Adding tests for unknown users * Adding wait for popover calls * Addressing design feedback * Addressing remaining feedback * Refactoring css and name prop * Refactoring popover * Refactoring search component * Addressing some feedback * Adjusting sorting * Fixing tests * Fixing type error * Fixing test error * Fixing test errors * Removing display name Co-authored-by: Thom Heymann Co-authored-by: Jonathan Buttner Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Thom Heymann <190132+thomheymann@users.noreply.github.com> Co-authored-by: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com> * [ResponseOps][Cases] Add assignee user actions (#139392) * Adding user actions for assignees * Fixing merge issues * Fixing test mock errors * Fixing display name errors and themselves * Fixing test for time being * Addressing feedback * Addressing comma and uniq feedback * Using core getUserDisplayName * Fixing import and removing flickering * Fixing tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * Detect when user is typing * Use select to tranform data * [Cases] Assign users when creating a case (#139754) * Init * Render users * Assign yourself * Add tests * Fix tests * PR feedback * [ResponseOps][Cases] Filter by assignees (#139441) * Starting the filtering * Rough draft working for assignees filtering * Adding integration tests for new route * Starting to write tests * Fixing tests * Cleaning up more tests * Removing duplicate call for current user * Fixing type errors and tests * Adding tests for filtering * Adding rbac tests * Fixing translations * Fixing api integration tests * Fixing severity tests * Really fixing arrays equal * Fixing ml tests and refactoring find assignees * Fixing cypress tests * Fixing types * Fix tests * Addressing first round of feedback * Reverting the recent cases changes * Fixing tests * Fixing more tests and types * Allowing multi select * Fixing attachment framework issue * Addressing feedback * Fixing type error * Fixing tests * Sort users and improve loading * Fix ml security dependecies * Fix permissions when fetching suggestions * Fixing read permissions and suggest api * Hiding assignee delete icon * Hiding the assign yourself text when undefined * Create page fixes Co-authored-by: Christos Nasikas Co-authored-by: Thom Heymann Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Thom Heymann <190132+thomheymann@users.noreply.github.com> --- .../src/user_profiles_popover.test.tsx | 3 +- .../src/user_profiles_selectable.test.tsx | 3 +- .../common/api/cases/suggest_user_profiles.ts | 18 - x-pack/plugins/cases/common/api/user.ts | 13 +- x-pack/plugins/cases/common/constants.ts | 5 + x-pack/plugins/cases/common/ui/types.ts | 3 +- .../plugins/cases/public/common/mock/index.ts | 1 + .../cases/public/common/mock/permissions.ts | 69 +++ .../public/common/mock/test_providers.tsx | 85 +-- .../all_cases/all_cases_list.test.tsx | 39 +- .../components/all_cases/all_cases_list.tsx | 37 +- .../all_cases/assignees_filter.test.tsx | 185 ++++++ .../components/all_cases/assignees_filter.tsx | 126 ++++ .../public/components/all_cases/columns.tsx | 76 ++- .../components/all_cases/index.test.tsx | 19 +- .../all_cases/table_filters.test.tsx | 75 +-- .../components/all_cases/table_filters.tsx | 49 +- .../components/all_cases/translations.ts | 21 + .../components/app/use_available_owners.ts | 5 +- .../case_view/case_view_page.test.tsx | 4 + .../components/assign_users.test.tsx | 402 +++++++++++++ .../case_view/components/assign_users.tsx | 213 +++++++ .../components/case_view_activity.test.tsx | 4 + .../components/case_view_activity.tsx | 55 +- .../components/edit_tags.test.tsx} | 24 +- .../components/edit_tags.tsx} | 28 +- .../case_view/components/sidebar_section.tsx | 30 + .../case_view/components/sidebar_title.tsx | 25 + .../components/suggest_users_popover.test.tsx | 238 ++++++++ .../components/suggest_users_popover.tsx | 144 +++++ .../components/user_list.test.tsx} | 6 +- .../components/user_list.tsx} | 4 +- .../components/case_view/translations.ts | 36 ++ .../case_view/use_on_update_field.ts | 9 + .../components/create/assignees.test.tsx | 153 +++++ .../public/components/create/assignees.tsx | 225 +++++++ .../cases/public/components/create/form.tsx | 4 + .../components/create/form_context.test.tsx | 552 ++++++++++-------- .../public/components/create/index.test.tsx | 3 +- .../cases/public/components/create/mock.ts | 1 + .../cases/public/components/create/schema.tsx | 1 + .../public/components/create/translations.ts | 5 + .../components/edit_connector/index.test.tsx | 16 +- .../editable_title.test.tsx.snap | 98 ---- .../__snapshots__/index.test.tsx.snap | 103 ---- .../header_page/editable_title.test.tsx | 19 +- .../components/header_page/index.test.tsx | 20 +- .../components/{tag_list => tags}/tags.tsx | 2 + .../{tag_list => tags}/translations.ts | 0 .../plugins/cases/public/components/types.ts | 4 + .../user_actions/assignees.test.tsx | 230 ++++++++ .../components/user_actions/assignees.tsx | 156 ++++- .../user_actions/comment/comment.tsx | 7 +- .../components/user_actions/index.test.tsx | 3 + .../public/components/user_actions/index.tsx | 6 + .../public/components/user_actions/mock.ts | 3 + .../public/components/user_actions/tags.tsx | 2 +- .../components/user_actions/translations.ts | 16 + .../public/components/user_actions/types.ts | 6 + .../data_test_subject.ts} | 7 +- .../user_profiles/display_name.test.ts | 38 ++ .../components/user_profiles/display_name.ts | 19 + .../user_profiles/empty_message.test.tsx | 17 + .../empty_message.tsx} | 11 +- .../user_profiles/no_matches.test.tsx | 18 + .../components/user_profiles/no_matches.tsx | 41 ++ .../selected_status_message.test.tsx | 24 + .../user_profiles/selected_status_message.tsx | 22 + .../components/user_profiles/sort.test.ts | 118 ++++ .../public/components/user_profiles/sort.ts | 53 ++ .../components/user_profiles/translations.ts | 52 ++ .../public/components/user_profiles/types.ts | 17 + .../components/user_profiles/unknown_user.tsx | 21 + .../user_profiles/user_avatar.test.tsx | 32 + .../components/user_profiles/user_avatar.tsx | 35 ++ .../user_representation.test.tsx | 86 +++ .../user_profiles/user_representation.tsx | 103 ++++ .../user_profiles/user_tooltip.test.tsx | 174 ++++++ .../components/user_profiles/user_tooltip.tsx | 105 ++++ .../cases/public/containers/__mocks__/api.ts | 8 +- .../cases/public/containers/api.test.tsx | 41 +- x-pack/plugins/cases/public/containers/api.ts | 2 + .../cases/public/containers/constants.ts | 1 + .../plugins/cases/public/containers/mock.ts | 23 +- .../use_get_case_user_actions.test.tsx | 79 +++ .../containers/use_get_case_user_actions.tsx | 18 + .../cases/public/containers/use_get_cases.tsx | 1 + .../containers/use_get_cases_metrics.test.tsx | 2 +- .../containers/use_get_reporters.test.tsx | 111 ---- .../public/containers/use_get_reporters.tsx | 95 --- .../containers/user_profiles/__mocks__/api.ts | 8 +- .../containers/user_profiles/api.mock.ts | 2 + .../containers/user_profiles/api.test.ts | 45 +- .../public/containers/user_profiles/api.ts | 20 +- .../user_profiles/use_assignees.test.ts | 113 ++++ .../containers/user_profiles/use_assignees.ts | 68 +++ .../use_bulk_get_user_profiles.test.ts | 59 +- .../use_bulk_get_user_profiles.ts | 18 +- .../use_get_current_user_profile.test.ts | 97 +++ .../use_get_current_user_profile.ts | 44 ++ .../use_suggest_user_profiles.test.ts | 2 +- .../use_suggest_user_profiles.ts | 34 +- .../cases/public/utils/permissions.test.ts | 37 ++ .../plugins/cases/public/utils/permissions.ts | 7 + x-pack/plugins/cases/server/features.ts | 2 +- .../server/services/user_profiles/index.ts | 62 +- .../application/util/dependency_cache.ts | 4 +- x-pack/plugins/ml/public/plugin.ts | 6 +- x-pack/plugins/observability/server/plugin.ts | 2 +- .../integration/cases/creation.spec.ts | 4 - .../cypress/screens/all_cases.ts | 5 - .../threat_hunting/cases/import_case.spec.ts | 2 - .../security_solution/server/features.ts | 2 +- .../apis/cases/bulk_get_user_profiles.ts | 6 +- .../test/api_integration/apis/cases/index.ts | 2 +- .../apis/cases/suggest_user_profiles.ts | 30 +- .../plugins/observability/server/plugin.ts | 3 +- .../security_solution/server/plugin.ts | 2 +- .../common/lib/authentication/index.ts | 2 +- .../common/lib/user_profiles.ts | 45 ++ .../cases_api_integration/common/lib/utils.ts | 45 -- .../common/lib/validation.ts | 6 +- .../tests/common/cases/assignees.ts | 3 +- .../tests/common/cases/find_cases.ts | 6 +- .../common/internal/suggest_user_profiles.ts | 15 +- .../common/metrics/get_case_metrics_alerts.ts | 8 +- .../common/internal/suggest_user_profiles.ts | 2 +- x-pack/test/functional/services/cases/api.ts | 18 + .../test/functional/services/cases/common.ts | 12 + .../test/functional/services/cases/create.ts | 2 +- .../test/functional/services/cases/index.ts | 2 +- x-pack/test/functional/services/cases/list.ts | 16 +- .../services/cases/single_case_view.ts | 10 + .../apps/cases/common/users.ts | 8 +- .../apps/cases/list_view.ts | 34 +- .../apps/cases/view_case.ts | 199 +++++-- .../fixtures/plugins/cases/kibana.json | 2 +- 137 files changed, 5000 insertions(+), 1184 deletions(-) delete mode 100644 x-pack/plugins/cases/common/api/cases/suggest_user_profiles.ts create mode 100644 x-pack/plugins/cases/public/common/mock/permissions.ts create mode 100644 x-pack/plugins/cases/public/components/all_cases/assignees_filter.test.tsx create mode 100644 x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx create mode 100644 x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx create mode 100644 x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx rename x-pack/plugins/cases/public/components/{tag_list/index.test.tsx => case_view/components/edit_tags.test.tsx} (86%) rename x-pack/plugins/cases/public/components/{tag_list/index.tsx => case_view/components/edit_tags.tsx} (90%) create mode 100644 x-pack/plugins/cases/public/components/case_view/components/sidebar_section.tsx create mode 100644 x-pack/plugins/cases/public/components/case_view/components/sidebar_title.tsx create mode 100644 x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx create mode 100644 x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx rename x-pack/plugins/cases/public/components/{user_list/index.test.tsx => case_view/components/user_list.test.tsx} (93%) rename x-pack/plugins/cases/public/components/{user_list/index.tsx => case_view/components/user_list.tsx} (97%) create mode 100644 x-pack/plugins/cases/public/components/create/assignees.test.tsx create mode 100644 x-pack/plugins/cases/public/components/create/assignees.tsx delete mode 100644 x-pack/plugins/cases/public/components/header_page/__snapshots__/editable_title.test.tsx.snap delete mode 100644 x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap rename x-pack/plugins/cases/public/components/{tag_list => tags}/tags.tsx (99%) rename x-pack/plugins/cases/public/components/{tag_list => tags}/translations.ts (100%) create mode 100644 x-pack/plugins/cases/public/components/user_actions/assignees.test.tsx rename x-pack/plugins/cases/public/components/{tag_list/schema.tsx => user_profiles/data_test_subject.ts} (61%) create mode 100644 x-pack/plugins/cases/public/components/user_profiles/display_name.test.ts create mode 100644 x-pack/plugins/cases/public/components/user_profiles/display_name.ts create mode 100644 x-pack/plugins/cases/public/components/user_profiles/empty_message.test.tsx rename x-pack/plugins/cases/public/components/{user_list/translations.ts => user_profiles/empty_message.tsx} (52%) create mode 100644 x-pack/plugins/cases/public/components/user_profiles/no_matches.test.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/no_matches.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/selected_status_message.test.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/selected_status_message.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/sort.test.ts create mode 100644 x-pack/plugins/cases/public/components/user_profiles/sort.ts create mode 100644 x-pack/plugins/cases/public/components/user_profiles/translations.ts create mode 100644 x-pack/plugins/cases/public/components/user_profiles/types.ts create mode 100644 x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/user_representation.test.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/user_representation.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx create mode 100644 x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx delete mode 100644 x-pack/plugins/cases/public/containers/use_get_reporters.test.tsx delete mode 100644 x-pack/plugins/cases/public/containers/use_get_reporters.tsx create mode 100644 x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts create mode 100644 x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts create mode 100644 x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts create mode 100644 x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts create mode 100644 x-pack/plugins/cases/public/utils/permissions.test.ts diff --git a/packages/kbn-user-profile-components/src/user_profiles_popover.test.tsx b/packages/kbn-user-profile-components/src/user_profiles_popover.test.tsx index 6f838631591cee..a68f09cba6a548 100644 --- a/packages/kbn-user-profile-components/src/user_profiles_popover.test.tsx +++ b/packages/kbn-user-profile-components/src/user_profiles_popover.test.tsx @@ -8,10 +8,11 @@ import { shallow } from 'enzyme'; import React from 'react'; +import { UserProfile } from './user_profile'; import { UserProfilesPopover } from './user_profiles_popover'; -const userProfiles = [ +const userProfiles: UserProfile[] = [ { uid: 'u_BOulL4QMPSyV9jg5lQI2JmCkUnokHTazBnet3xVHNv0_0', enabled: true, diff --git a/packages/kbn-user-profile-components/src/user_profiles_selectable.test.tsx b/packages/kbn-user-profile-components/src/user_profiles_selectable.test.tsx index ad3b3c94ac6dad..05eb4966496a05 100644 --- a/packages/kbn-user-profile-components/src/user_profiles_selectable.test.tsx +++ b/packages/kbn-user-profile-components/src/user_profiles_selectable.test.tsx @@ -8,10 +8,11 @@ import { mount } from 'enzyme'; import React from 'react'; +import { UserProfile } from './user_profile'; import { UserProfilesSelectable } from './user_profiles_selectable'; -const userProfiles = [ +const userProfiles: UserProfile[] = [ { uid: 'u_BOulL4QMPSyV9jg5lQI2JmCkUnokHTazBnet3xVHNv0_0', enabled: true, diff --git a/x-pack/plugins/cases/common/api/cases/suggest_user_profiles.ts b/x-pack/plugins/cases/common/api/cases/suggest_user_profiles.ts deleted file mode 100644 index 75cd1f9cb9f94f..00000000000000 --- a/x-pack/plugins/cases/common/api/cases/suggest_user_profiles.ts +++ /dev/null @@ -1,18 +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 * as rt from 'io-ts'; - -export const SuggestUserProfilesRequestRt = rt.intersection([ - rt.type({ - name: rt.string, - owners: rt.array(rt.string), - }), - rt.partial({ size: rt.number }), -]); - -export type SuggestUserProfilesRequest = rt.TypeOf; diff --git a/x-pack/plugins/cases/common/api/user.ts b/x-pack/plugins/cases/common/api/user.ts index 2696ad60a4568e..63280d230b7778 100644 --- a/x-pack/plugins/cases/common/api/user.ts +++ b/x-pack/plugins/cases/common/api/user.ts @@ -7,11 +7,14 @@ import * as rt from 'io-ts'; -export const UserRT = rt.type({ - email: rt.union([rt.undefined, rt.null, rt.string]), - full_name: rt.union([rt.undefined, rt.null, rt.string]), - username: rt.union([rt.undefined, rt.null, rt.string]), -}); +export const UserRT = rt.intersection([ + rt.type({ + email: rt.union([rt.undefined, rt.null, rt.string]), + full_name: rt.union([rt.undefined, rt.null, rt.string]), + username: rt.union([rt.undefined, rt.null, rt.string]), + }), + rt.partial({ profile_uid: rt.string }), +]); export const UsersRt = rt.array(UserRT); diff --git a/x-pack/plugins/cases/common/constants.ts b/x-pack/plugins/cases/common/constants.ts index 9e85d6e4cbf7a3..ccc4ada609d037 100644 --- a/x-pack/plugins/cases/common/constants.ts +++ b/x-pack/plugins/cases/common/constants.ts @@ -163,3 +163,8 @@ export const PUSH_CASES_CAPABILITY = 'push_cases' as const; */ export const DEFAULT_USER_SIZE = 10; + +/** + * Delays + */ +export const SEARCH_DEBOUNCE_MS = 500; diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index 9fef8ae47b3b0b..2ae40c2e339617 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -103,6 +103,7 @@ export interface FilterOptions { severity: CaseSeverityWithAll; status: CaseStatusWithAllStatus; tags: string[]; + assignees: string[]; reporters: User[]; owner: string[]; } @@ -162,7 +163,7 @@ export interface FieldMappings { export type UpdateKey = keyof Pick< CasePatchRequest, - 'connector' | 'description' | 'status' | 'tags' | 'title' | 'settings' | 'severity' + 'connector' | 'description' | 'status' | 'tags' | 'title' | 'settings' | 'severity' | 'assignees' >; export interface UpdateByKey { diff --git a/x-pack/plugins/cases/public/common/mock/index.ts b/x-pack/plugins/cases/public/common/mock/index.ts index add4c1c206dd4c..c607eb2985af83 100644 --- a/x-pack/plugins/cases/public/common/mock/index.ts +++ b/x-pack/plugins/cases/public/common/mock/index.ts @@ -6,3 +6,4 @@ */ export * from './test_providers'; +export * from './permissions'; diff --git a/x-pack/plugins/cases/public/common/mock/permissions.ts b/x-pack/plugins/cases/public/common/mock/permissions.ts new file mode 100644 index 00000000000000..1166dbed8ca881 --- /dev/null +++ b/x-pack/plugins/cases/public/common/mock/permissions.ts @@ -0,0 +1,69 @@ +/* + * 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 { CasesCapabilities, CasesPermissions } from '../../containers/types'; + +export const allCasesPermissions = () => buildCasesPermissions(); +export const noCasesPermissions = () => + buildCasesPermissions({ read: false, create: false, update: false, delete: false, push: false }); +export const readCasesPermissions = () => + buildCasesPermissions({ read: true, create: false, update: false, delete: false, push: false }); +export const noCreateCasesPermissions = () => buildCasesPermissions({ create: false }); +export const noUpdateCasesPermissions = () => buildCasesPermissions({ update: false }); +export const noPushCasesPermissions = () => buildCasesPermissions({ push: false }); +export const noDeleteCasesPermissions = () => buildCasesPermissions({ delete: false }); +export const writeCasesPermissions = () => buildCasesPermissions({ read: false }); + +export const buildCasesPermissions = (overrides: Partial> = {}) => { + const create = overrides.create ?? true; + const read = overrides.read ?? true; + const update = overrides.update ?? true; + const deletePermissions = overrides.delete ?? true; + const push = overrides.push ?? true; + const all = create && read && update && deletePermissions && push; + + return { + all, + create, + read, + update, + delete: deletePermissions, + push, + }; +}; + +export const allCasesCapabilities = () => buildCasesCapabilities(); +export const noCasesCapabilities = () => + buildCasesCapabilities({ + create_cases: false, + read_cases: false, + update_cases: false, + delete_cases: false, + push_cases: false, + }); +export const readCasesCapabilities = () => + buildCasesCapabilities({ + create_cases: false, + update_cases: false, + delete_cases: false, + push_cases: false, + }); +export const writeCasesCapabilities = () => { + return buildCasesCapabilities({ + read_cases: false, + }); +}; + +export const buildCasesCapabilities = (overrides?: Partial) => { + return { + create_cases: overrides?.create_cases ?? true, + read_cases: overrides?.read_cases ?? true, + update_cases: overrides?.update_cases ?? true, + delete_cases: overrides?.delete_cases ?? true, + push_cases: overrides?.push_cases ?? true, + }; +}; diff --git a/x-pack/plugins/cases/public/common/mock/test_providers.tsx b/x-pack/plugins/cases/public/common/mock/test_providers.tsx index dceb8fd0f30a71..a180fb942bd158 100644 --- a/x-pack/plugins/cases/public/common/mock/test_providers.tsx +++ b/x-pack/plugins/cases/public/common/mock/test_providers.tsx @@ -5,6 +5,8 @@ * 2.0. */ +/* eslint-disable no-console */ + import React from 'react'; import { euiDarkVars } from '@kbn/ui-theme'; import { I18nProvider } from '@kbn/i18n-react'; @@ -14,7 +16,7 @@ import { render as reactRender, RenderOptions, RenderResult } from '@testing-lib import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; -import { CasesCapabilities, CasesFeatures, CasesPermissions } from '../../../common/ui/types'; +import { CasesFeatures, CasesPermissions } from '../../../common/ui/types'; import { CasesProvider } from '../../components/cases_context'; import { createKibanaContextProviderMock, @@ -25,6 +27,7 @@ import { StartServices } from '../../types'; import { ReleasePhase } from '../../components/types'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; +import { allCasesPermissions } from './permissions'; interface TestProviderProps { children: React.ReactNode; @@ -56,6 +59,11 @@ const TestProvidersComponent: React.FC = ({ retry: false, }, }, + logger: { + log: console.log, + warn: console.warn, + error: () => {}, + }, }); return ( @@ -98,69 +106,17 @@ export const testQueryClient = new QueryClient({ retry: false, }, }, + /** + * React query prints the errors in the console even though + * all tests are passings. We turn them off for testing. + */ + logger: { + log: console.log, + warn: console.warn, + error: () => {}, + }, }); -export const allCasesPermissions = () => buildCasesPermissions(); -export const noCasesPermissions = () => - buildCasesPermissions({ read: false, create: false, update: false, delete: false, push: false }); -export const readCasesPermissions = () => - buildCasesPermissions({ read: true, create: false, update: false, delete: false, push: false }); -export const noCreateCasesPermissions = () => buildCasesPermissions({ create: false }); -export const noUpdateCasesPermissions = () => buildCasesPermissions({ update: false }); -export const noPushCasesPermissions = () => buildCasesPermissions({ push: false }); -export const noDeleteCasesPermissions = () => buildCasesPermissions({ delete: false }); -export const writeCasesPermissions = () => buildCasesPermissions({ read: false }); - -export const buildCasesPermissions = (overrides: Partial> = {}) => { - const create = overrides.create ?? true; - const read = overrides.read ?? true; - const update = overrides.update ?? true; - const deletePermissions = overrides.delete ?? true; - const push = overrides.push ?? true; - const all = create && read && update && deletePermissions && push; - - return { - all, - create, - read, - update, - delete: deletePermissions, - push, - }; -}; - -export const allCasesCapabilities = () => buildCasesCapabilities(); -export const noCasesCapabilities = () => - buildCasesCapabilities({ - create_cases: false, - read_cases: false, - update_cases: false, - delete_cases: false, - push_cases: false, - }); -export const readCasesCapabilities = () => - buildCasesCapabilities({ - create_cases: false, - update_cases: false, - delete_cases: false, - push_cases: false, - }); -export const writeCasesCapabilities = () => { - return buildCasesCapabilities({ - read_cases: false, - }); -}; - -export const buildCasesCapabilities = (overrides?: Partial) => { - return { - create_cases: overrides?.create_cases ?? true, - read_cases: overrides?.read_cases ?? true, - update_cases: overrides?.update_cases ?? true, - delete_cases: overrides?.delete_cases ?? true, - push_cases: overrides?.push_cases ?? true, - }; -}; - export const createAppMockRenderer = ({ features, owner = [SECURITY_SOLUTION_OWNER], @@ -176,6 +132,11 @@ export const createAppMockRenderer = ({ retry: false, }, }, + logger: { + log: console.log, + warn: console.warn, + error: () => {}, + }, }); const AppWrapper: React.FC<{ children: React.ReactElement }> = ({ children }) => ( diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx index d8aedbc10bd3de..c38408c8f54173 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx @@ -37,12 +37,14 @@ import { registerConnectorsToMockActionRegistry } from '../../common/mock/regist import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; import { waitForComponentToUpdate } from '../../common/test_utils'; import { useCreateAttachments } from '../../containers/use_create_attachments'; -import { useGetReporters } from '../../containers/use_get_reporters'; import { useGetCasesMetrics } from '../../containers/use_get_cases_metrics'; import { useGetConnectors } from '../../containers/configure/use_connectors'; import { useGetTags } from '../../containers/use_get_tags'; import { useUpdateCase } from '../../containers/use_update_case'; import { useGetCases } from '../../containers/use_get_cases'; +import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get_current_user_profile'; +import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; +import { useBulkGetUserProfiles } from '../../containers/user_profiles/use_bulk_get_user_profiles'; jest.mock('../../containers/use_create_attachments'); jest.mock('../../containers/use_bulk_update_case'); @@ -52,7 +54,8 @@ jest.mock('../../containers/use_get_cases_status'); jest.mock('../../containers/use_get_cases_metrics'); jest.mock('../../containers/use_get_action_license'); jest.mock('../../containers/use_get_tags'); -jest.mock('../../containers/use_get_reporters'); +jest.mock('../../containers/user_profiles/use_get_current_user_profile'); +jest.mock('../../containers/user_profiles/use_bulk_get_user_profiles'); jest.mock('../../containers/configure/use_connectors'); jest.mock('../../common/lib/kibana'); jest.mock('../../common/navigation/hooks'); @@ -67,7 +70,8 @@ const useGetCasesStatusMock = useGetCasesStatus as jest.Mock; const useGetCasesMetricsMock = useGetCasesMetrics as jest.Mock; const useUpdateCasesMock = useUpdateCases as jest.Mock; const useGetTagsMock = useGetTags as jest.Mock; -const useGetReportersMock = useGetReporters as jest.Mock; +const useGetCurrentUserProfileMock = useGetCurrentUserProfile as jest.Mock; +const useBulkGetUserProfilesMock = useBulkGetUserProfiles as jest.Mock; const useKibanaMock = useKibana as jest.MockedFunction; const useGetConnectorsMock = useGetConnectors as jest.Mock; const useCreateAttachmentsMock = useCreateAttachments as jest.Mock; @@ -145,6 +149,8 @@ describe('AllCasesListGeneric', () => { handleIsLoading: jest.fn(), isLoadingCases: [], isSelectorView: false, + userProfiles: new Map(), + currentUserProfile: undefined, }; let appMockRenderer: AppMockRenderer; @@ -164,13 +170,8 @@ describe('AllCasesListGeneric', () => { useGetCasesStatusMock.mockReturnValue(defaultCasesStatus); useGetCasesMetricsMock.mockReturnValue(defaultCasesMetrics); useGetTagsMock.mockReturnValue({ data: ['coke', 'pepsi'], refetch: jest.fn() }); - useGetReportersMock.mockReturnValue({ - reporters: ['casetester'], - respReporters: [{ username: 'casetester' }], - isLoading: true, - isError: false, - fetchReporters: jest.fn(), - }); + useGetCurrentUserProfileMock.mockReturnValue({ data: userProfiles[0], isLoading: false }); + useBulkGetUserProfilesMock.mockReturnValue({ data: userProfilesMap }); useGetConnectorsMock.mockImplementation(() => ({ data: connectorsMock, isLoading: false })); useUpdateCaseMock.mockReturnValue({ updateCaseProperty }); mockKibana(); @@ -194,9 +195,9 @@ describe('AllCasesListGeneric', () => { expect( wrapper.find(`span[data-test-subj="case-table-column-tags-coke"]`).first().prop('title') ).toEqual(useGetCasesMockState.data.cases[0].tags[0]); - expect(wrapper.find(`[data-test-subj="case-table-column-createdBy"]`).first().text()).toEqual( - 'LK' - ); + expect( + wrapper.find(`[data-test-subj="case-user-profile-avatar-damaged_raccoon"]`).first().text() + ).toEqual('DR'); expect( wrapper .find(`[data-test-subj="case-table-column-createdAt"]`) @@ -215,20 +216,17 @@ describe('AllCasesListGeneric', () => { }); }); - it('should show a tooltip with the reporter username when hover over the reporter avatar', async () => { + it("should show a tooltip with the assignee's email when hover over the assignee avatar", async () => { const result = render( ); - userEvent.hover(result.queryAllByTestId('case-table-column-createdBy')[0]); + userEvent.hover(result.queryAllByTestId('case-user-profile-avatar-damaged_raccoon')[0]); await waitFor(() => { - expect(result.getByTestId('case-table-column-createdBy-tooltip')).toBeTruthy(); - expect(result.getByTestId('case-table-column-createdBy-tooltip').textContent).toEqual( - 'lknope' - ); + expect(result.getByText('damaged_raccoon@elastic.co')).toBeInTheDocument(); }); }); @@ -263,6 +261,7 @@ describe('AllCasesListGeneric', () => { title: null, totalComment: null, totalAlerts: null, + assignees: [], }, ], }, @@ -588,7 +587,7 @@ describe('AllCasesListGeneric', () => { wrapper.find('[data-test-subj="cases-table-row-select-1"]').first().simulate('click'); await waitFor(() => { expect(onRowClick).toHaveBeenCalledWith({ - assignees: [], + assignees: [{ uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }], closedAt: null, closedBy: null, comments: [], diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx index 3c056ccf996dd7..ce38c82f083841 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx @@ -10,6 +10,7 @@ import { EuiProgress, EuiBasicTable, EuiTableSelectionType } from '@elastic/eui' import { difference, head, isEmpty } from 'lodash/fp'; import styled, { css } from 'styled-components'; +import { useQueryClient } from '@tanstack/react-query'; import { Case, CaseStatusWithAllStatus, @@ -35,6 +36,12 @@ import { initialData, useGetCases, } from '../../containers/use_get_cases'; +import { useBulkGetUserProfiles } from '../../containers/user_profiles/use_bulk_get_user_profiles'; +import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get_current_user_profile'; +import { + USER_PROFILES_BULK_GET_CACHE_KEY, + USER_PROFILES_CACHE_KEY, +} from '../../containers/constants'; const ProgressLoader = styled(EuiProgress)` ${({ $isShow }: { $isShow: boolean }) => @@ -78,6 +85,7 @@ export const AllCasesList = React.memo( }); const [queryParams, setQueryParams] = useState(DEFAULT_QUERY_PARAMS); const [selectedCases, setSelectedCases] = useState([]); + const queryClient = useQueryClient(); const { data = initialData, @@ -88,6 +96,26 @@ export const AllCasesList = React.memo( queryParams, }); + const assigneesFromCases = useMemo(() => { + return data.cases.reduce>((acc, caseInfo) => { + if (!caseInfo) { + return acc; + } + + for (const assignee of caseInfo.assignees) { + acc.add(assignee.uid); + } + return acc; + }, new Set()); + }, [data.cases]); + + const { data: userProfiles } = useBulkGetUserProfiles({ + uids: Array.from(assigneesFromCases), + }); + + const { data: currentUserProfile, isLoading: isLoadingCurrentUserProfile } = + useGetCurrentUserProfile(); + const { data: connectors = [] } = useGetConnectors(); const sorting = useMemo( @@ -118,6 +146,8 @@ export const AllCasesList = React.memo( deselectCases(); if (dataRefresh) { refetchCases(); + queryClient.refetchQueries([USER_PROFILES_CACHE_KEY, USER_PROFILES_BULK_GET_CACHE_KEY]); + setRefresh((currRefresh: number) => currRefresh + 1); } if (doRefresh) { @@ -127,7 +157,7 @@ export const AllCasesList = React.memo( filterRefetch.current(); } }, - [deselectCases, doRefresh, refetchCases] + [deselectCases, doRefresh, queryClient, refetchCases] ); const tableOnChangeCallback = useCallback( @@ -193,6 +223,8 @@ export const AllCasesList = React.memo( const columns = useCasesColumns({ filterStatus: filterOptions.status ?? StatusAll, + userProfiles: userProfiles ?? new Map(), + currentUserProfile, handleIsLoading, refreshCases, isSelectorView, @@ -245,6 +277,7 @@ export const AllCasesList = React.memo( initial={{ search: filterOptions.search, searchFields: filterOptions.searchFields, + assignees: filterOptions.assignees, reporters: filterOptions.reporters, tags: filterOptions.tags, status: filterOptions.status, @@ -255,6 +288,8 @@ export const AllCasesList = React.memo( hiddenStatuses={hiddenStatuses} displayCreateCaseButton={isSelectorView} onCreateCasePressed={onRowClick} + isLoading={isLoadingCurrentUserProfile} + currentUserProfile={currentUserProfile} /> { + let appMockRender: AppMockRenderer; + let defaultProps: AssigneesFilterPopoverProps; + + beforeEach(() => { + jest.clearAllMocks(); + + appMockRender = createAppMockRenderer(); + + defaultProps = { + currentUserProfile: undefined, + selectedAssignees: [], + isLoading: false, + onSelectionChange: jest.fn(), + }; + }); + + it('calls onSelectionChange when 1 user is selected', async () => { + const onSelectionChange = jest.fn(); + const props = { ...defaultProps, onSelectionChange }; + appMockRender.render(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + expect(screen.getByPlaceholderText('Search users')).toBeInTheDocument(); + }); + await waitForEuiPopoverOpen(); + + fireEvent.change(screen.getByPlaceholderText('Search users'), { target: { value: 'dingo' } }); + userEvent.click(screen.getByText('wet_dingo@elastic.co')); + + expect(onSelectionChange.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + ] + `); + }); + + it('calls onSelectionChange with a single user when different users are selected', async () => { + const onSelectionChange = jest.fn(); + const props = { ...defaultProps, onSelectionChange }; + appMockRender.render(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + expect(screen.getByText('wet_dingo@elastic.co')); + }); + + await waitForEuiPopoverOpen(); + + fireEvent.change(screen.getByPlaceholderText('Search users'), { target: { value: 'dingo' } }); + userEvent.click(screen.getByText('wet_dingo@elastic.co')); + userEvent.click(screen.getByText('damaged_raccoon@elastic.co')); + + expect(onSelectionChange.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + ] + `); + expect(onSelectionChange.mock.calls[1][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + ] + `); + }); + + it('does not show the assigned users total if there are no assigned users', async () => { + appMockRender.render(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + }); + + await waitForEuiPopoverOpen(); + + expect(screen.queryByText('assignee')).not.toBeInTheDocument(); + }); + + it('shows the 1 assigned total when the users are passed in', async () => { + const props = { + ...defaultProps, + selectedAssignees: [userProfiles[0]], + }; + appMockRender.render(); + + await waitFor(async () => { + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + expect(screen.getByText('1 assignee filtered')).toBeInTheDocument(); + }); + + await waitForEuiPopoverOpen(); + + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + }); + + it('shows three users when initially rendered', async () => { + appMockRender.render(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + expect(screen.getByText('Wet Dingo')).toBeInTheDocument(); + }); + await waitForEuiPopoverOpen(); + + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument(); + }); + + it('shows the users sorted alphabetically with the current user at the front', async () => { + const props = { + ...defaultProps, + currentUserProfile: userProfiles[2], + }; + + appMockRender.render(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + expect(screen.getByText('Wet Dingo')).toBeInTheDocument(); + }); + await waitForEuiPopoverOpen(); + + const assignees = screen.getAllByRole('option'); + expect(within(assignees[0]).getByText('Wet Dingo')).toBeInTheDocument(); + expect(within(assignees[1]).getByText('Damaged Raccoon')).toBeInTheDocument(); + expect(within(assignees[2]).getByText('Physical Dinosaur')).toBeInTheDocument(); + }); + + it('does not show the number of filters', async () => { + appMockRender.render(); + + await waitFor(() => { + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + expect(screen.getByText('Wet Dingo')).toBeInTheDocument(); + }); + await waitForEuiPopoverOpen(); + + expect(screen.queryByText('3')).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx b/x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx new file mode 100644 index 00000000000000..6ffa18cfa80734 --- /dev/null +++ b/x-pack/plugins/cases/public/components/all_cases/assignees_filter.tsx @@ -0,0 +1,126 @@ +/* + * 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 { EuiFilterButton } from '@elastic/eui'; +import { UserProfilesPopover, UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { isEmpty } from 'lodash'; +import React, { useCallback, useMemo, useState } from 'react'; +import { useSuggestUserProfiles } from '../../containers/user_profiles/use_suggest_user_profiles'; +import { useAvailableCasesOwners } from '../app/use_available_owners'; +import { useCasesContext } from '../cases_context/use_cases_context'; +import { CurrentUserProfile } from '../types'; +import { EmptyMessage } from '../user_profiles/empty_message'; +import { NoMatches } from '../user_profiles/no_matches'; +import { SelectedStatusMessage } from '../user_profiles/selected_status_message'; +import { bringCurrentUserToFrontAndSort } from '../user_profiles/sort'; +import * as i18n from './translations'; + +export interface AssigneesFilterPopoverProps { + selectedAssignees: UserProfileWithAvatar[]; + currentUserProfile: CurrentUserProfile; + isLoading: boolean; + onSelectionChange: (users: UserProfileWithAvatar[]) => void; +} + +const AssigneesFilterPopoverComponent: React.FC = ({ + selectedAssignees, + currentUserProfile, + isLoading, + onSelectionChange, +}) => { + const { owner: owners } = useCasesContext(); + const hasOwners = owners.length > 0; + const availableOwners = useAvailableCasesOwners(['read']); + const [searchTerm, setSearchTerm] = useState(''); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const togglePopover = useCallback(() => setIsPopoverOpen((value) => !value), []); + + const onChange = useCallback( + (users: UserProfileWithAvatar[]) => { + const sortedUsers = bringCurrentUserToFrontAndSort(currentUserProfile, users); + onSelectionChange(sortedUsers ?? []); + }, + [currentUserProfile, onSelectionChange] + ); + + const selectedStatusMessage = useCallback( + (selectedCount: number) => ( + + ), + [] + ); + + const onSearchChange = useCallback((term: string) => { + setSearchTerm(term); + + if (!isEmpty(term)) { + setIsUserTyping(true); + } + }, []); + + const [isUserTyping, setIsUserTyping] = useState(false); + + const onDebounce = useCallback(() => setIsUserTyping(false), []); + + const { data: userProfiles, isLoading: isLoadingSuggest } = useSuggestUserProfiles({ + name: searchTerm, + owners: hasOwners ? owners : availableOwners, + onDebounce, + }); + + const searchResultProfiles = useMemo( + () => bringCurrentUserToFrontAndSort(currentUserProfile, userProfiles), + [userProfiles, currentUserProfile] + ); + + const isLoadingData = isLoading || isLoadingSuggest; + + return ( + 0} + numActiveFilters={selectedAssignees.length} + aria-label={i18n.FILTER_ASSIGNEES_ARIA_LABEL} + > + {i18n.ASSIGNEES} + + } + selectableProps={{ + onChange, + onSearchChange, + selectedStatusMessage, + options: searchResultProfiles, + selectedOptions: selectedAssignees, + isLoading: isLoadingData || isUserTyping, + height: 'full', + searchPlaceholder: i18n.SEARCH_USERS, + clearButtonLabel: i18n.CLEAR_FILTERS, + emptyMessage: , + noMatchesMessage: !isUserTyping && !isLoadingData ? : , + singleSelection: false, + }} + /> + ); +}; +AssigneesFilterPopoverComponent.displayName = 'AssigneesFilterPopover'; + +export const AssigneesFilterPopover = React.memo(AssigneesFilterPopoverComponent); diff --git a/x-pack/plugins/cases/public/components/all_cases/columns.tsx b/x-pack/plugins/cases/public/components/all_cases/columns.tsx index 0929f8971cf06e..be5b8ace2e2b69 100644 --- a/x-pack/plugins/cases/public/components/all_cases/columns.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/columns.tsx @@ -7,7 +7,6 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { - EuiAvatar, EuiBadgeGroup, EuiBadge, EuiButton, @@ -24,6 +23,7 @@ import { import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services'; import styled from 'styled-components'; +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { Case, DeleteCase, UpdateByKey } from '../../../common/ui/types'; import { CaseStatuses, ActionConnector, CaseSeverity } from '../../../common/api'; import { OWNER_INFO } from '../../../common/constants'; @@ -44,6 +44,11 @@ import { useCasesFeatures } from '../cases_context/use_cases_features'; import { severities } from '../severity/config'; import { useUpdateCase } from '../../containers/use_update_case'; import { useCasesContext } from '../cases_context/use_cases_context'; +import { UserToolTip } from '../user_profiles/user_tooltip'; +import { CaseUserAvatar } from '../user_profiles/user_avatar'; +import { useAssignees } from '../../containers/user_profiles/use_assignees'; +import { getUsernameDataTestSubj } from '../user_profiles/data_test_subject'; +import { CurrentUserProfile } from '../types'; export type CasesColumns = | EuiTableActionsColumnType @@ -57,8 +62,45 @@ const MediumShadeText = styled.p` const renderStringField = (field: string, dataTestSubj: string) => field != null ? {field} : getEmptyTagValue(); +const AssigneesColumn: React.FC<{ + assignees: Case['assignees']; + userProfiles: Map; + currentUserProfile: CurrentUserProfile; +}> = ({ assignees, userProfiles, currentUserProfile }) => { + const { allAssignees } = useAssignees({ + caseAssignees: assignees, + userProfiles, + currentUserProfile, + }); + + if (allAssignees.length <= 0) { + return getEmptyTagValue(); + } + + return ( + + {allAssignees.map((assignee) => { + const dataTestSubjName = getUsernameDataTestSubj(assignee); + return ( + + + + + + ); + })} + + ); +}; +AssigneesColumn.displayName = 'AssigneesColumn'; export interface GetCasesColumn { filterStatus: string; + userProfiles: Map; + currentUserProfile: CurrentUserProfile; handleIsLoading: (a: boolean) => void; refreshCases?: (a?: boolean) => void; isSelectorView: boolean; @@ -69,6 +111,8 @@ export interface GetCasesColumn { } export const useCasesColumns = ({ filterStatus, + userProfiles, + currentUserProfile, handleIsLoading, refreshCases, isSelectorView, @@ -173,27 +217,15 @@ export const useCasesColumns = ({ }, }, { - field: 'createdBy', - name: i18n.REPORTER, - render: (createdBy: Case['createdBy']) => { - if (createdBy != null) { - return ( - - - - ); - } - return getEmptyTagValue(); - }, + field: 'assignees', + name: i18n.ASSIGNEES, + render: (assignees: Case['assignees']) => ( + + ), }, { field: 'tags', diff --git a/x-pack/plugins/cases/public/components/all_cases/index.test.tsx b/x-pack/plugins/cases/public/components/all_cases/index.test.tsx index 8e5263a31ff3df..38f0b9d53b1d16 100644 --- a/x-pack/plugins/cases/public/components/all_cases/index.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/index.test.tsx @@ -16,15 +16,16 @@ import { noCreateCasesPermissions, TestProviders, } from '../../common/mock'; -import { useGetReporters } from '../../containers/use_get_reporters'; import { useGetActionLicense } from '../../containers/use_get_action_license'; import { casesStatus, connectorsMock, useGetCasesMockState } from '../../containers/mock'; import { useGetCasesStatus } from '../../containers/use_get_cases_status'; import { useGetConnectors } from '../../containers/configure/use_connectors'; import { useGetTags } from '../../containers/use_get_tags'; import { useGetCases } from '../../containers/use_get_cases'; +import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get_current_user_profile'; +import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; +import { useBulkGetUserProfiles } from '../../containers/user_profiles/use_bulk_get_user_profiles'; -jest.mock('../../containers/use_get_reporters'); jest.mock('../../containers/use_get_tags'); jest.mock('../../containers/use_get_action_license', () => { return { @@ -35,11 +36,15 @@ jest.mock('../../containers/configure/use_connectors'); jest.mock('../../containers/api'); jest.mock('../../containers/use_get_cases'); jest.mock('../../containers/use_get_cases_status'); +jest.mock('../../containers/user_profiles/use_get_current_user_profile'); +jest.mock('../../containers/user_profiles/use_bulk_get_user_profiles'); const useGetConnectorsMock = useGetConnectors as jest.Mock; const useGetCasesMock = useGetCases as jest.Mock; const useGetCasesStatusMock = useGetCasesStatus as jest.Mock; const useGetActionLicenseMock = useGetActionLicense as jest.Mock; +const useGetCurrentUserProfileMock = useGetCurrentUserProfile as jest.Mock; +const useBulkGetUserProfilesMock = useBulkGetUserProfiles as jest.Mock; describe('AllCases', () => { const refetchCases = jest.fn(); @@ -71,17 +76,13 @@ describe('AllCases', () => { beforeAll(() => { (useGetTags as jest.Mock).mockReturnValue({ data: ['coke', 'pepsi'], refetch: jest.fn() }); - (useGetReporters as jest.Mock).mockReturnValue({ - reporters: ['casetester'], - respReporters: [{ username: 'casetester' }], - isLoading: true, - isError: false, - fetchReporters: jest.fn(), - }); useGetConnectorsMock.mockImplementation(() => ({ data: connectorsMock, isLoading: false })); useGetCasesStatusMock.mockReturnValue(defaultCasesStatus); useGetActionLicenseMock.mockReturnValue(defaultActionLicense); useGetCasesMock.mockReturnValue(defaultGetCases); + + useGetCurrentUserProfileMock.mockReturnValue({ data: userProfiles[0], isLoading: false }); + useBulkGetUserProfilesMock.mockReturnValue({ data: userProfilesMap }); }); let appMockRender: AppMockRenderer; diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx index 4c477e1b4a581e..23a8772852e17d 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx @@ -7,22 +7,23 @@ import React from 'react'; import { mount } from 'enzyme'; +import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import { CaseStatuses } from '../../../common/api'; import { OBSERVABILITY_OWNER, SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; -import { useGetReporters } from '../../containers/use_get_reporters'; import { DEFAULT_FILTER_OPTIONS } from '../../containers/use_get_cases'; import { CasesTableFilters } from './table_filters'; import { useGetTags } from '../../containers/use_get_tags'; +import { useSuggestUserProfiles } from '../../containers/user_profiles/use_suggest_user_profiles'; +import { userProfiles } from '../../containers/user_profiles/api.mock'; -jest.mock('../../containers/use_get_reporters'); jest.mock('../../containers/use_get_tags'); +jest.mock('../../containers/user_profiles/use_suggest_user_profiles'); const onFilterChanged = jest.fn(); -const fetchReporters = jest.fn(); const refetch = jest.fn(); const setFilterRefetch = jest.fn(); @@ -34,6 +35,8 @@ const props = { initial: DEFAULT_FILTER_OPTIONS, setFilterRefetch, availableSolutions: [], + isLoading: false, + currentUserProfile: undefined, }; describe('CasesTableFilters ', () => { @@ -42,13 +45,7 @@ describe('CasesTableFilters ', () => { appMockRender = createAppMockRenderer(); jest.clearAllMocks(); (useGetTags as jest.Mock).mockReturnValue({ data: ['coke', 'pepsi'], refetch }); - (useGetReporters as jest.Mock).mockReturnValue({ - reporters: ['casetester'], - respReporters: [{ username: 'casetester' }], - isLoading: true, - isError: false, - fetchReporters, - }); + (useSuggestUserProfiles as jest.Mock).mockReturnValue({ data: userProfiles, isLoading: false }); }); it('should render the case status filter dropdown', () => { @@ -87,23 +84,20 @@ describe('CasesTableFilters ', () => { expect(onFilterChanged).toBeCalledWith({ tags: ['coke'] }); }); - it('should call onFilterChange when selected reporters change', () => { - const wrapper = mount( - - - - ); - wrapper - .find(`[data-test-subj="options-filter-popover-button-Reporter"]`) - .last() - .simulate('click'); + it('should call onFilterChange when selected assignees change', async () => { + const { getByTestId, getByText } = appMockRender.render(); + userEvent.click(getByTestId('options-filter-popover-button-assignees')); + await waitForEuiPopoverOpen(); - wrapper - .find(`[data-test-subj="options-filter-popover-item-casetester"]`) - .last() - .simulate('click'); + userEvent.click(getByText('Physical Dinosaur')); - expect(onFilterChanged).toBeCalledWith({ reporters: [{ username: 'casetester' }] }); + expect(onFilterChanged.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "assignees": Array [ + "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + ], + } + `); }); it('should call onFilterChange when search changes', () => { @@ -157,23 +151,32 @@ describe('CasesTableFilters ', () => { expect(onFilterChanged).toHaveBeenCalledWith({ tags: ['pepsi'] }); }); - it('should remove reporter from selected reporters when reporter no longer exists', () => { - const ourProps = { + it('should remove assignee from selected assignees when assignee no longer exists', async () => { + const overrideProps = { ...props, initial: { ...DEFAULT_FILTER_OPTIONS, - reporters: [ - { username: 'casetester', full_name: null, email: null }, - { username: 'batman', full_name: null, email: null }, + assignees: [ + // invalid profile uid + '123', + 'u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0', ], }, }; - mount( - - - - ); - expect(onFilterChanged).toHaveBeenCalledWith({ reporters: [{ username: 'casetester' }] }); + + appMockRender.render(); + userEvent.click(screen.getByTestId('options-filter-popover-button-assignees')); + await waitForEuiPopoverOpen(); + + userEvent.click(screen.getByText('Physical Dinosaur')); + + expect(onFilterChanged.mock.calls[0][0]).toMatchInlineSnapshot(` + Object { + "assignees": Array [ + "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + ], + } + `); }); it('StatusFilterWrapper should have a fixed width of 180px', () => { diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx index cedd7c9b647187..25da22f9be1686 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx @@ -10,10 +10,10 @@ import { isEqual } from 'lodash/fp'; import styled from 'styled-components'; import { EuiFlexGroup, EuiFlexItem, EuiFieldSearch, EuiFilterGroup, EuiButton } from '@elastic/eui'; +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { StatusAll, CaseStatusWithAllStatus, CaseSeverityWithAll } from '../../../common/ui/types'; import { CaseStatuses } from '../../../common/api'; import { FilterOptions } from '../../containers/types'; -import { useGetReporters } from '../../containers/use_get_reporters'; import { FilterPopover } from '../filter_popover'; import { StatusFilter } from './status_filter'; import * as i18n from './translations'; @@ -21,6 +21,8 @@ import { SeverityFilter } from './severity_filter'; import { useGetTags } from '../../containers/use_get_tags'; import { CASE_LIST_CACHE_KEY } from '../../containers/constants'; import { DEFAULT_FILTER_OPTIONS } from '../../containers/use_get_cases'; +import { AssigneesFilterPopover } from './assignees_filter'; +import { CurrentUserProfile } from '../types'; interface CasesTableFiltersProps { countClosedCases: number | null; @@ -33,6 +35,8 @@ interface CasesTableFiltersProps { availableSolutions: string[]; displayCreateCaseButton?: boolean; onCreateCasePressed?: () => void; + isLoading: boolean; + currentUserProfile: CurrentUserProfile; } // Fix the width of the status dropdown to prevent hiding long text items @@ -59,20 +63,18 @@ const CasesTableFiltersComponent = ({ availableSolutions, displayCreateCaseButton, onCreateCasePressed, + isLoading, + currentUserProfile, }: CasesTableFiltersProps) => { - const [selectedReporters, setSelectedReporters] = useState( - initial.reporters.map((r) => r.full_name ?? r.username ?? '') - ); const [search, setSearch] = useState(initial.search); const [selectedTags, setSelectedTags] = useState(initial.tags); const [selectedOwner, setSelectedOwner] = useState(initial.owner); + const [selectedAssignees, setSelectedAssignees] = useState([]); const { data: tags = [], refetch: fetchTags } = useGetTags(CASE_LIST_CACHE_KEY); - const { reporters, respReporters, fetchReporters } = useGetReporters(); const refetch = useCallback(() => { fetchTags(); - fetchReporters(); - }, [fetchReporters, fetchTags]); + }, [fetchTags]); useEffect(() => { if (setFilterRefetch != null) { @@ -80,26 +82,16 @@ const CasesTableFiltersComponent = ({ } }, [refetch, setFilterRefetch]); - const handleSelectedReporters = useCallback( - (newReporters) => { - if (!isEqual(newReporters, selectedReporters)) { - setSelectedReporters(newReporters); - const reportersObj = respReporters.filter( - (r) => newReporters.includes(r.username) || newReporters.includes(r.full_name) - ); - onFilterChanged({ reporters: reportersObj }); + const handleSelectedAssignees = useCallback( + (newAssignees: UserProfileWithAvatar[]) => { + if (!isEqual(newAssignees, selectedAssignees)) { + setSelectedAssignees(newAssignees); + onFilterChanged({ assignees: newAssignees.map((assignee) => assignee.uid) }); } }, - [selectedReporters, respReporters, onFilterChanged] + [selectedAssignees, onFilterChanged] ); - useEffect(() => { - if (selectedReporters.length) { - const newReporters = selectedReporters.filter((r) => reporters.includes(r)); - handleSelectedReporters(newReporters); - } - }, [handleSelectedReporters, reporters, selectedReporters]); - const handleSelectedTags = useCallback( (newTags) => { if (!isEqual(newTags, selectedTags)) { @@ -202,12 +194,11 @@ const CasesTableFiltersComponent = ({ - + i18n.translate('xpack.cases.allCasesView.totalFilteredUsers', { + defaultMessage: '{total, plural, one {# assignee} other {# assignees}} filtered', + values: { total }, + }); diff --git a/x-pack/plugins/cases/public/components/app/use_available_owners.ts b/x-pack/plugins/cases/public/components/app/use_available_owners.ts index 8715af5d6fa68c..9e593fa6c282ad 100644 --- a/x-pack/plugins/cases/public/components/app/use_available_owners.ts +++ b/x-pack/plugins/cases/public/components/app/use_available_owners.ts @@ -8,8 +8,9 @@ import { APP_ID, FEATURE_ID } from '../../../common/constants'; import { useKibana } from '../../common/lib/kibana'; import { CasesPermissions } from '../../containers/types'; +import { allCasePermissions } from '../../utils/permissions'; -type Capability = Omit; +type Capability = Exclude; /** * @@ -18,7 +19,7 @@ type Capability = Omit; **/ export const useAvailableCasesOwners = ( - capabilities: Capability[] = ['create', 'read', 'update', 'delete', 'push'] + capabilities: Capability[] = allCasePermissions ): string[] => { const { capabilities: kibanaCapabilities } = useKibana().services.application; diff --git a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx index 284785b33d7207..3855f14134f46b 100644 --- a/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/case_view_page.test.tsx @@ -21,6 +21,7 @@ import { useGetCaseUserActions } from '../../containers/use_get_case_user_action import { useGetTags } from '../../containers/use_get_tags'; import { usePostPushToService } from '../../containers/use_post_push_to_service'; import { useUpdateCase } from '../../containers/use_update_case'; +import { useBulkGetUserProfiles } from '../../containers/user_profiles/use_bulk_get_user_profiles'; import { CaseViewPage } from './case_view_page'; import { caseData, @@ -40,6 +41,7 @@ jest.mock('../../containers/use_get_tags'); jest.mock('../../containers/use_get_case'); jest.mock('../../containers/configure/use_connectors'); jest.mock('../../containers/use_post_push_to_service'); +jest.mock('../../containers/user_profiles/use_bulk_get_user_profiles'); jest.mock('../user_actions/timestamp', () => ({ UserActionTimestamp: () => <>, })); @@ -56,6 +58,7 @@ const useGetConnectorsMock = useGetConnectors as jest.Mock; const usePostPushToServiceMock = usePostPushToService as jest.Mock; const useGetCaseMetricsMock = useGetCaseMetrics as jest.Mock; const useGetTagsMock = useGetTags as jest.Mock; +const useBulkGetUserProfilesMock = useBulkGetUserProfiles as jest.Mock; const mockGetCase = (props: Partial = {}) => { const data = { @@ -96,6 +99,7 @@ describe('CaseViewPage', () => { usePostPushToServiceMock.mockReturnValue({ isLoading: false, pushCaseToExternalService }); useGetConnectorsMock.mockReturnValue({ data: connectorsMock, isLoading: false }); useGetTagsMock.mockReturnValue({ data: [], isLoading: false }); + useBulkGetUserProfilesMock.mockReturnValue({ data: new Map(), isLoading: false }); appMockRenderer = createAppMockRenderer(); }); diff --git a/x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx new file mode 100644 index 00000000000000..fdd4b5cb77e7d7 --- /dev/null +++ b/x-pack/plugins/cases/public/components/case_view/components/assign_users.test.tsx @@ -0,0 +1,402 @@ +/* + * 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 { useSuggestUserProfiles } from '../../../containers/user_profiles/use_suggest_user_profiles'; +import { useGetCurrentUserProfile } from '../../../containers/user_profiles/use_get_current_user_profile'; +import { userProfiles, userProfilesMap } from '../../../containers/user_profiles/api.mock'; +import { fireEvent, screen, waitFor } from '@testing-library/react'; +import React from 'react'; +import { + AppMockRenderer, + createAppMockRenderer, + noUpdateCasesPermissions, +} from '../../../common/mock'; +import { AssignUsers, AssignUsersProps } from './assign_users'; +import { waitForEuiPopoverClose, waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; + +jest.mock('../../../containers/user_profiles/use_suggest_user_profiles'); +jest.mock('../../../containers/user_profiles/use_get_current_user_profile'); + +const useSuggestUserProfilesMock = useSuggestUserProfiles as jest.Mock; +const useGetCurrentUserProfileMock = useGetCurrentUserProfile as jest.Mock; + +const currentUserProfile = userProfiles[0]; + +describe('AssignUsers', () => { + let appMockRender: AppMockRenderer; + let defaultProps: AssignUsersProps; + + beforeEach(() => { + defaultProps = { + caseAssignees: [], + currentUserProfile, + userProfiles: new Map(), + onAssigneesChanged: jest.fn(), + isLoading: false, + }; + + useSuggestUserProfilesMock.mockReturnValue({ data: userProfiles, isLoading: false }); + useGetCurrentUserProfileMock.mockReturnValue({ data: currentUserProfile, isLoading: false }); + + appMockRender = createAppMockRenderer(); + }); + + it('does not show any assignees when there are none assigned', () => { + appMockRender.render(); + + expect(screen.getByText('No users have been assigned.')).toBeInTheDocument(); + }); + + it('does not show the suggest users edit button when the user does not have update permissions', () => { + appMockRender = createAppMockRenderer({ permissions: noUpdateCasesPermissions() }); + appMockRender.render(); + + expect(screen.queryByText('case-view-assignees-edit')).not.toBeInTheDocument(); + }); + + it('does not show the assign users link when the user does not have update permissions', () => { + appMockRender = createAppMockRenderer({ permissions: noUpdateCasesPermissions() }); + appMockRender.render(); + + expect(screen.queryByTestId('assign yourself')).not.toBeInTheDocument(); + expect(screen.queryByTestId('Assign a user')).not.toBeInTheDocument(); + }); + + it('does not show the suggest users edit button when the component is still loading', () => { + appMockRender.render(); + + expect(screen.queryByTestId('case-view-assignees-edit')).not.toBeInTheDocument(); + expect(screen.getByTestId('case-view-assignees-button-loading')).toBeInTheDocument(); + }); + + it('does not show the assign yourself link when the current profile is undefined', () => { + appMockRender.render(); + + expect(screen.queryByText('assign yourself')).not.toBeInTheDocument(); + expect(screen.getByText('Assign a user')).toBeInTheDocument(); + }); + + it('shows the suggest users edit button when the user has update permissions', () => { + appMockRender.render(); + + expect(screen.getByTestId('case-view-assignees-edit')).toBeInTheDocument(); + }); + + it('shows the two initially assigned users', () => { + const props = { + ...defaultProps, + caseAssignees: userProfiles.slice(0, 2), + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument(); + expect(screen.queryByText('Wet Dingo')).not.toBeInTheDocument(); + expect(screen.queryByText('No users have been assigned.')).not.toBeInTheDocument(); + expect(screen.queryByTestId('case-view-assignees-loading')).not.toBeInTheDocument(); + }); + + it('shows the rerendered assignees', () => { + const { rerender } = appMockRender.render(); + + const props = { + ...defaultProps, + caseAssignees: userProfiles.slice(0, 2), + userProfiles: userProfilesMap, + }; + rerender(); + + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument(); + expect(screen.queryByText('Wet Dingo')).not.toBeInTheDocument(); + expect(screen.queryByText('No users have been assigned.')).not.toBeInTheDocument(); + expect(screen.queryByTestId('case-view-assignees-loading')).not.toBeInTheDocument(); + }); + + it('shows the popover when the pencil is clicked', async () => { + const props = { + ...defaultProps, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverOpen(); + fireEvent.change(screen.getByPlaceholderText('Search users'), { + target: { value: 'damaged_raccoon@elastic.co' }, + }); + + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + }); + + it('shows the popover when the assign a user link is clicked', async () => { + const props = { + ...defaultProps, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.click(screen.getByText('Assign a user')); + await waitForEuiPopoverOpen(); + fireEvent.change(screen.getByPlaceholderText('Search users'), { + target: { value: 'damaged_raccoon@elastic.co' }, + }); + + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + }); + + it('assigns the current user when the assign yourself link is clicked', async () => { + const onAssigneesChanged = jest.fn(); + const props = { + ...defaultProps, + onAssigneesChanged, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.click(screen.getByText('assign yourself')); + + await waitFor(() => expect(onAssigneesChanged).toBeCalledTimes(1)); + + expect(onAssigneesChanged.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + ] + `); + }); + + it('calls onAssigneesChanged with an empty array because all the users were deleted', async () => { + const onAssigneesChanged = jest.fn(); + const props = { + ...defaultProps, + caseAssignees: [{ uid: userProfiles[0].uid }], + onAssigneesChanged, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.mouseEnter( + screen.getByTestId(`user-profile-assigned-user-group-${userProfiles[0].user.username}`) + ); + fireEvent.click( + screen.getByTestId(`user-profile-assigned-user-cross-${userProfiles[0].user.username}`) + ); + + await waitFor(() => expect(onAssigneesChanged).toBeCalledTimes(1)); + + expect(onAssigneesChanged.mock.calls[0][0]).toMatchInlineSnapshot(`Array []`); + }); + + it('calls onAssigneesChanged when the popover is closed using the pencil button', async () => { + const onAssigneesChanged = jest.fn(); + const props = { + ...defaultProps, + onAssigneesChanged, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverOpen(); + fireEvent.change(screen.getByPlaceholderText('Search users'), { + target: { value: 'damaged_raccoon@elastic.co' }, + }); + + fireEvent.click(screen.getByText('Damaged Raccoon')); + + // close the popover + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverClose(); + + await waitFor(() => expect(onAssigneesChanged).toBeCalledTimes(1)); + + expect(onAssigneesChanged.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + ] + `); + }); + + it('does not call onAssigneesChanged when the selected assignees have not changed between renders', async () => { + const onAssigneesChanged = jest.fn(); + const props = { + ...defaultProps, + caseAssignees: [{ uid: userProfiles[0].uid }], + onAssigneesChanged, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverOpen(); + + // close the popover + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverClose(); + + await waitFor(() => expect(onAssigneesChanged).toBeCalledTimes(0)); + }); + + it('calls onAssigneesChanged without unknownId1', async () => { + const onAssigneesChanged = jest.fn(); + const props = { + ...defaultProps, + caseAssignees: [{ uid: 'unknownId1' }, { uid: 'unknownId2' }], + onAssigneesChanged, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.mouseEnter(screen.getByTestId(`user-profile-assigned-user-group-unknownId1`)); + fireEvent.click(screen.getByTestId(`user-profile-assigned-user-cross-unknownId1`)); + + await waitFor(() => expect(onAssigneesChanged).toBeCalledTimes(1)); + + expect(onAssigneesChanged.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "uid": "unknownId2", + }, + ] + `); + }); + + it('renders two unknown users and one user with a profile', async () => { + const props = { + ...defaultProps, + caseAssignees: [{ uid: 'unknownId1' }, { uid: 'unknownId2' }, { uid: userProfiles[0].uid }], + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + expect(screen.getByTestId('user-profile-assigned-user-group-unknownId1')).toBeInTheDocument(); + expect(screen.getByTestId('user-profile-assigned-user-group-unknownId2')).toBeInTheDocument(); + }); + + it('calls onAssigneesChanged with both users with profiles and without', async () => { + const onAssigneesChanged = jest.fn(); + const props = { + ...defaultProps, + caseAssignees: [{ uid: 'unknownId1' }, { uid: 'unknownId2' }], + onAssigneesChanged, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverOpen(); + fireEvent.change(screen.getByPlaceholderText('Search users'), { + target: { value: 'damaged_raccoon@elastic.co' }, + }); + + fireEvent.click(screen.getByText('Damaged Raccoon')); + + // close the popover + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverClose(); + + await waitFor(() => expect(onAssigneesChanged).toBeCalledTimes(1)); + + expect(onAssigneesChanged.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + Object { + "uid": "unknownId1", + }, + Object { + "uid": "unknownId2", + }, + ] + `); + }); + + it('calls onAssigneesChanged with the unknown users at the end', async () => { + const onAssigneesChanged = jest.fn(); + const props = { + ...defaultProps, + caseAssignees: [{ uid: userProfiles[1].uid }, { uid: 'unknownId1' }, { uid: 'unknownId2' }], + onAssigneesChanged, + userProfiles: userProfilesMap, + }; + appMockRender.render(); + + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverOpen(); + + fireEvent.change(screen.getByPlaceholderText('Search users'), { + target: { value: 'damaged_raccoon@elastic.co' }, + }); + + fireEvent.click(screen.getByText('Damaged Raccoon')); + + // close the popover + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + await waitForEuiPopoverClose(); + + await waitFor(() => expect(onAssigneesChanged).toBeCalledTimes(1)); + + expect(onAssigneesChanged.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + "user": Object { + "email": "physical_dinosaur@elastic.co", + "full_name": "Physical Dinosaur", + "username": "physical_dinosaur", + }, + }, + Object { + "uid": "unknownId1", + }, + Object { + "uid": "unknownId2", + }, + ] + `); + }); +}); diff --git a/x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx b/x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx new file mode 100644 index 00000000000000..520c76fef51243 --- /dev/null +++ b/x-pack/plugins/cases/public/components/case_view/components/assign_users.tsx @@ -0,0 +1,213 @@ +/* + * 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, { useCallback, useEffect, useState } from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiLink, + EuiLoadingSpinner, + EuiSpacer, +} from '@elastic/eui'; + +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { CasesPermissions } from '../../../../common'; +import { useAssignees } from '../../../containers/user_profiles/use_assignees'; +import { CaseAssignees } from '../../../../common/api/cases/assignee'; +import * as i18n from '../translations'; +import { SidebarTitle } from './sidebar_title'; +import { UserRepresentation } from '../../user_profiles/user_representation'; +import { useCasesContext } from '../../cases_context/use_cases_context'; +import { Assignee } from '../../user_profiles/types'; +import { SuggestUsersPopover } from './suggest_users_popover'; +import { CurrentUserProfile } from '../../types'; + +interface AssigneesListProps { + assignees: Assignee[]; + currentUserProfile: CurrentUserProfile; + permissions: CasesPermissions; + assignSelf: () => void; + togglePopOver: () => void; + onAssigneeRemoved: (removedAssigneeUID: string) => void; +} + +const AssigneesList: React.FC = ({ + assignees, + currentUserProfile, + permissions, + assignSelf, + togglePopOver, + onAssigneeRemoved, +}) => { + return ( + <> + {assignees.length === 0 ? ( + + + +

+ {i18n.NO_ASSIGNEES} + {permissions.update && ( + <> +
+ + {i18n.ASSIGN_A_USER} + + + )} + {currentUserProfile && permissions.update && ( + <> + {i18n.SPACED_OR} + + {i18n.ASSIGN_YOURSELF} + + + )} +

+
+
+
+ ) : ( + + {assignees.map((assignee) => ( + + + + ))} + + )} + + ); +}; +AssigneesList.displayName = 'AssigneesList'; + +export interface AssignUsersProps { + caseAssignees: CaseAssignees; + currentUserProfile: CurrentUserProfile; + userProfiles: Map; + onAssigneesChanged: (assignees: Assignee[]) => void; + isLoading: boolean; +} + +const AssignUsersComponent: React.FC = ({ + caseAssignees, + userProfiles, + currentUserProfile, + onAssigneesChanged, + isLoading, +}) => { + const { assigneesWithProfiles, assigneesWithoutProfiles, allAssignees } = useAssignees({ + caseAssignees, + userProfiles, + currentUserProfile, + }); + + const [selectedAssignees, setSelectedAssignees] = useState(); + const [needToUpdateAssignees, setNeedToUpdateAssignees] = useState(false); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + const togglePopover = useCallback(() => { + setIsPopoverOpen((value) => !value); + setNeedToUpdateAssignees(true); + }, []); + + const onClosePopover = useCallback(() => { + // Order matters here because needToUpdateAssignees will likely be true already + // from the togglePopover call when opening the popover, so if we set the popover to false + // first, we'll get a rerender and then get another after we set needToUpdateAssignees to true again + setNeedToUpdateAssignees(true); + setIsPopoverOpen(false); + }, []); + + const onAssigneeRemoved = useCallback( + (removedAssigneeUID: string) => { + const remainingAssignees = allAssignees.filter( + (assignee) => assignee.uid !== removedAssigneeUID + ); + setSelectedAssignees(remainingAssignees); + setNeedToUpdateAssignees(true); + }, + [allAssignees] + ); + + const onUsersChange = useCallback( + (users: UserProfileWithAvatar[]) => { + // if users are selected then also include the users without profiles + if (users.length > 0) { + setSelectedAssignees([...users, ...assigneesWithoutProfiles]); + } else { + // all users were deselected so lets remove the users without profiles as well + setSelectedAssignees([]); + } + }, + [assigneesWithoutProfiles] + ); + + const assignSelf = useCallback(() => { + if (!currentUserProfile) { + return; + } + + const newAssignees = [currentUserProfile, ...allAssignees]; + setSelectedAssignees(newAssignees); + setNeedToUpdateAssignees(true); + }, [currentUserProfile, allAssignees]); + + const { permissions } = useCasesContext(); + + useEffect(() => { + // selectedAssignees will be undefined on initial render or a rerender occurs, so we only want to update the assignees + // after the users have been changed in some manner not when it is an initial value + if (isPopoverOpen === false && needToUpdateAssignees && selectedAssignees) { + setNeedToUpdateAssignees(false); + onAssigneesChanged(selectedAssignees); + } + }, [isPopoverOpen, needToUpdateAssignees, onAssigneesChanged, selectedAssignees]); + + return ( + + + + + + {isLoading && } + {!isLoading && permissions.update && ( + + + + )} + + + + + ); +}; + +AssignUsersComponent.displayName = 'AssignUsers'; + +export const AssignUsers = React.memo(AssignUsersComponent); diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx index db5411525290b5..74ff651a0a11c5 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx @@ -26,6 +26,7 @@ import { useGetCaseUserActions } from '../../../containers/use_get_case_user_act import { usePostPushToService } from '../../../containers/use_post_push_to_service'; import { useGetConnectors } from '../../../containers/configure/use_connectors'; import { useGetTags } from '../../../containers/use_get_tags'; +import { useBulkGetUserProfiles } from '../../../containers/user_profiles/use_bulk_get_user_profiles'; jest.mock('../../../containers/use_get_case_user_actions'); jest.mock('../../../containers/configure/use_connectors'); @@ -36,6 +37,7 @@ jest.mock('../../user_actions/timestamp', () => ({ jest.mock('../../../common/navigation/hooks'); jest.mock('../../../containers/use_get_action_license'); jest.mock('../../../containers/use_get_tags'); +jest.mock('../../../containers/user_profiles/use_bulk_get_user_profiles'); (useGetTags as jest.Mock).mockReturnValue({ data: ['coke', 'pepsi'], refetch: jest.fn() }); @@ -93,12 +95,14 @@ export const caseProps = { const useGetCaseUserActionsMock = useGetCaseUserActions as jest.Mock; const useGetConnectorsMock = useGetConnectors as jest.Mock; const usePostPushToServiceMock = usePostPushToService as jest.Mock; +const useBulkGetUserProfilesMock = useBulkGetUserProfiles as jest.Mock; describe('Case View Page activity tab', () => { beforeAll(() => { useGetCaseUserActionsMock.mockReturnValue(defaultUseGetCaseUserActions); useGetConnectorsMock.mockReturnValue({ data: connectorsMock, isLoading: false }); usePostPushToServiceMock.mockReturnValue({ isLoading: false, pushCaseToExternalService }); + useBulkGetUserProfilesMock.mockReturnValue({ isLoading: false, data: new Map() }); }); let appMockRender: AppMockRenderer; diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx index 1e935c15891f42..647763d5461d19 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.tsx @@ -7,6 +7,9 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingContent } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; +import { isEqual, uniq } from 'lodash'; +import { useGetCurrentUserProfile } from '../../../containers/user_profiles/use_get_current_user_profile'; +import { useBulkGetUserProfiles } from '../../../containers/user_profiles/use_bulk_get_user_profiles'; import { useGetConnectors } from '../../../containers/configure/use_connectors'; import { CaseSeverity } from '../../../../common/api'; import { useCaseViewNavigation } from '../../../common/navigation'; @@ -15,9 +18,9 @@ import { Case, CaseStatuses } from '../../../../common'; import { EditConnector } from '../../edit_connector'; import { CasesNavigation } from '../../links'; import { StatusActionButton } from '../../status/button'; -import { TagList } from '../../tag_list'; +import { EditTags } from './edit_tags'; import { UserActions } from '../../user_actions'; -import { UserList } from '../../user_list'; +import { UserList } from './user_list'; import { useOnUpdateField } from '../use_on_update_field'; import { useCasesContext } from '../../cases_context/use_cases_context'; import * as i18n from '../translations'; @@ -25,6 +28,9 @@ import { getNoneConnector, normalizeActionConnector } from '../../configure_case import { getConnectorById } from '../../utils'; import { SeveritySidebarSelector } from '../../severity/sidebar_selector'; import { useGetCaseUserActions } from '../../../containers/use_get_case_user_actions'; +import { AssignUsers } from './assign_users'; +import { SidebarSection } from './sidebar_section'; +import { Assignee } from '../../user_profiles/types'; export const CaseViewActivity = ({ ruleDetailsNavigation, @@ -47,6 +53,21 @@ export const CaseViewActivity = ({ caseData.connector.id ); + const assignees = useMemo( + () => caseData.assignees.map((assignee) => assignee.uid), + [caseData.assignees] + ); + + const userActionProfileUids = Array.from(userActionsData?.profileUids?.values() ?? []); + const uidsToRetrieve = uniq([...userActionProfileUids, ...assignees]); + + const { data: userProfiles, isFetching: isLoadingUserProfiles } = useBulkGetUserProfiles({ + uids: uidsToRetrieve, + }); + + const { data: currentUserProfile, isFetching: isLoadingCurrentUserProfile } = + useGetCurrentUserProfile(); + const onShowAlertDetails = useCallback( (alertId: string, index: string) => { if (showAlertDetails) { @@ -61,6 +82,11 @@ export const CaseViewActivity = ({ caseData, }); + const isLoadingAssigneeData = + (isLoading && loadingKey === 'assignees') || + isLoadingUserProfiles || + isLoadingCurrentUserProfile; + const changeStatus = useCallback( (status: CaseStatuses) => onUpdateField({ @@ -88,6 +114,16 @@ export const CaseViewActivity = ({ [onUpdateField] ); + const onUpdateAssignees = useCallback( + (newAssignees: Assignee[]) => { + const newAssigneeUids = newAssignees.map((assignee) => ({ uid: assignee.uid })); + if (!isEqual(newAssigneeUids.sort(), assignees.sort())) { + onUpdateField({ key: 'assignees', value: newAssigneeUids }); + } + }, + [assignees, onUpdateField] + ); + const { isLoading: isLoadingConnectors, data: connectors = [] } = useGetConnectors(); const [connectorName, isValidConnector] = useMemo(() => { @@ -118,10 +154,12 @@ export const CaseViewActivity = ({ {isLoadingUserActions && ( )} - {!isLoadingUserActions && userActionsData && ( + {!isLoadingUserActions && userActionsData && userProfiles && ( + + + ) : null} - ({ @@ -32,13 +32,13 @@ jest.mock('@elastic/eui', () => { }; }); const onSubmit = jest.fn(); -const defaultProps: TagListProps = { +const defaultProps: EditTagsProps = { isLoading: false, onSubmit, tags: [], }; -describe('TagList ', () => { +describe('EditTags ', () => { const sampleTags = ['coke', 'pepsi']; const fetchTags = jest.fn(); const formHookMock = getFormMock({ tags: sampleTags }); @@ -55,7 +55,7 @@ describe('TagList ', () => { it('Renders no tags, and then edit', () => { const wrapper = mount( - + ); expect(wrapper.find(`[data-test-subj="no-tags"]`).last().exists()).toBeTruthy(); @@ -67,7 +67,7 @@ describe('TagList ', () => { it('Edit tag on submit', async () => { const wrapper = mount( - + ); wrapper.find(`[data-test-subj="tag-list-edit-button"]`).last().simulate('click'); @@ -78,7 +78,7 @@ describe('TagList ', () => { it('Tag options render with new tags added', () => { const wrapper = mount( - + ); wrapper.find(`[data-test-subj="tag-list-edit-button"]`).last().simulate('click'); @@ -94,7 +94,7 @@ describe('TagList ', () => { }; const wrapper = mount( - + ); @@ -110,7 +110,7 @@ describe('TagList ', () => { it('does not render when the user does not have update permissions', () => { const wrapper = mount( - + ); expect(wrapper.find(`[data-test-subj="tag-list-edit"]`).exists()).toBeFalsy(); diff --git a/x-pack/plugins/cases/public/components/tag_list/index.tsx b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.tsx similarity index 90% rename from x-pack/plugins/cases/public/components/tag_list/index.tsx rename to x-pack/plugins/cases/public/components/case_view/components/edit_tags.tsx index c85f989f882819..0dd651f6c92515 100644 --- a/x-pack/plugins/cases/public/components/tag_list/index.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/edit_tags.tsx @@ -18,17 +18,27 @@ import { } from '@elastic/eui'; import styled, { css } from 'styled-components'; import { isEqual } from 'lodash/fp'; -import * as i18n from './translations'; -import { Form, FormDataProvider, useForm, getUseField, Field } from '../../common/shared_imports'; -import { schema } from './schema'; -import { useGetTags } from '../../containers/use_get_tags'; +import * as i18n from '../../tags/translations'; +import { + Form, + FormDataProvider, + useForm, + getUseField, + Field, + FormSchema, +} from '../../../common/shared_imports'; +import { useGetTags } from '../../../containers/use_get_tags'; +import { Tags } from '../../tags/tags'; +import { useCasesContext } from '../../cases_context/use_cases_context'; +import { schemaTags } from '../../create/schema'; -import { Tags } from './tags'; -import { useCasesContext } from '../cases_context/use_cases_context'; +export const schema: FormSchema = { + tags: schemaTags, +}; const CommonUseField = getUseField({ component: Field }); -export interface TagListProps { +export interface EditTagsProps { isLoading: boolean; onSubmit: (a: string[]) => void; tags: string[]; @@ -55,7 +65,7 @@ const ColumnFlexGroup = styled(EuiFlexGroup)` `} `; -export const TagList = React.memo(({ isLoading, onSubmit, tags }: TagListProps) => { +export const EditTags = React.memo(({ isLoading, onSubmit, tags }: EditTagsProps) => { const { permissions } = useCasesContext(); const initialState = { tags }; const { form } = useForm({ @@ -194,4 +204,4 @@ export const TagList = React.memo(({ isLoading, onSubmit, tags }: TagListProps) ); }); -TagList.displayName = 'TagList'; +EditTags.displayName = 'EditTags'; diff --git a/x-pack/plugins/cases/public/components/case_view/components/sidebar_section.tsx b/x-pack/plugins/cases/public/components/case_view/components/sidebar_section.tsx new file mode 100644 index 00000000000000..d7b61e16b36b69 --- /dev/null +++ b/x-pack/plugins/cases/public/components/case_view/components/sidebar_section.tsx @@ -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 React from 'react'; +import { EuiHorizontalRule } from '@elastic/eui'; + +interface SidebarSectionProps { + children: React.ReactNode; + showHorizontalRule?: boolean; +} + +const SidebarSectionComponent: React.FC = ({ + children, + showHorizontalRule = true, +}) => { + return ( + <> + {children} + {showHorizontalRule ? : null} + + ); +}; + +SidebarSectionComponent.displayName = 'SidebarSection'; + +export const SidebarSection = React.memo(SidebarSectionComponent); diff --git a/x-pack/plugins/cases/public/components/case_view/components/sidebar_title.tsx b/x-pack/plugins/cases/public/components/case_view/components/sidebar_title.tsx new file mode 100644 index 00000000000000..b9ee1dd871b8e0 --- /dev/null +++ b/x-pack/plugins/cases/public/components/case_view/components/sidebar_title.tsx @@ -0,0 +1,25 @@ +/* + * 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 { EuiTitle } from '@elastic/eui'; + +interface SidebarTitleProps { + title: string; +} + +const SidebarTitleComponent: React.FC = ({ title }) => { + return ( + +

{title}

+
+ ); +}; + +SidebarTitleComponent.displayName = 'SidebarTitle'; + +export const SidebarTitle = React.memo(SidebarTitleComponent); diff --git a/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx new file mode 100644 index 00000000000000..27115acf5697f0 --- /dev/null +++ b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.test.tsx @@ -0,0 +1,238 @@ +/* + * 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 { AppMockRenderer, createAppMockRenderer } from '../../../common/mock'; +import { screen, fireEvent, waitFor } from '@testing-library/react'; +import { SuggestUsersPopoverProps, SuggestUsersPopover } from './suggest_users_popover'; +import { userProfiles } from '../../../containers/user_profiles/api.mock'; +import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { AssigneeWithProfile } from '../../user_profiles/types'; + +jest.mock('../../../containers/user_profiles/api'); + +describe('SuggestUsersPopover', () => { + let appMockRender: AppMockRenderer; + let defaultProps: SuggestUsersPopoverProps; + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + + defaultProps = { + isLoading: false, + assignedUsersWithProfiles: [], + isPopoverOpen: true, + onUsersChange: jest.fn(), + togglePopover: jest.fn(), + onClosePopover: jest.fn(), + currentUserProfile: undefined, + }; + }); + + it('calls onUsersChange when 1 user is selected', async () => { + const onUsersChange = jest.fn(); + const props = { ...defaultProps, onUsersChange }; + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + fireEvent.change(screen.getByPlaceholderText('Search users'), { target: { value: 'dingo' } }); + + await waitFor(() => { + expect(screen.getByText('wet_dingo@elastic.co')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getByText('wet_dingo@elastic.co')); + + expect(onUsersChange.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + ] + `); + }); + + it('calls onUsersChange when multiple users are selected', async () => { + const onUsersChange = jest.fn(); + const props = { ...defaultProps, onUsersChange }; + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + fireEvent.change(screen.getByPlaceholderText('Search users'), { target: { value: 'elastic' } }); + + await waitFor(() => { + expect(screen.getByText('wet_dingo@elastic.co')).toBeInTheDocument(); + expect(screen.getByText('damaged_raccoon@elastic.co')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getByText('wet_dingo@elastic.co')); + fireEvent.click(screen.getByText('damaged_raccoon@elastic.co')); + + expect(onUsersChange.mock.calls[1][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + ] + `); + }); + + it('calls onUsersChange with the current user (Physical Dinosaur) at the beginning', async () => { + const onUsersChange = jest.fn(); + const props = { + ...defaultProps, + assignedUsersWithProfiles: [asAssignee(userProfiles[1]), asAssignee(userProfiles[0])], + currentUserProfile: userProfiles[1], + onUsersChange, + }; + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + fireEvent.change(screen.getByPlaceholderText('Search users'), { target: { value: 'elastic' } }); + + await waitFor(() => { + expect(screen.getByText('wet_dingo@elastic.co')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getByText('wet_dingo@elastic.co')); + + expect(onUsersChange.mock.calls[0][0]).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + "user": Object { + "email": "physical_dinosaur@elastic.co", + "full_name": "Physical Dinosaur", + "username": "physical_dinosaur", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + ] + `); + }); + + it('does not show the assigned users total if there are no assigned users', async () => { + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + expect(screen.queryByText('assigned')).not.toBeInTheDocument(); + fireEvent.change(screen.getByPlaceholderText('Search users'), { target: { value: 'dingo' } }); + + await waitFor(() => { + expect(screen.getByText('wet_dingo@elastic.co')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getByText('wet_dingo@elastic.co')); + expect(screen.getByText('1 assigned')).toBeInTheDocument(); + }); + + it('shows the 1 assigned total after clicking on a user', async () => { + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + expect(screen.queryByText('assigned')).not.toBeInTheDocument(); + fireEvent.change(screen.getByPlaceholderText('Search users'), { target: { value: 'dingo' } }); + fireEvent.click(screen.getByText('wet_dingo@elastic.co')); + expect(screen.getByText('1 assigned')).toBeInTheDocument(); + }); + + it('shows the 1 assigned total when the users are passed in', async () => { + const props = { + ...defaultProps, + assignedUsersWithProfiles: [{ uid: userProfiles[0].uid, profile: userProfiles[0] }], + }; + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + expect(screen.getByText('1 assigned')).toBeInTheDocument(); + expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument(); + }); + + it('calls onTogglePopover when clicking the edit button after the popover is already open', async () => { + const togglePopover = jest.fn(); + const props = { + ...defaultProps, + togglePopover, + }; + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + await waitFor(() => { + expect(screen.getByTestId('case-view-assignees-edit-button')).not.toBeDisabled(); + }); + + fireEvent.click(screen.getByTestId('case-view-assignees-edit-button')); + + expect(togglePopover).toBeCalled(); + }); + + it('shows results initially', async () => { + appMockRender.render(); + + await waitForEuiPopoverOpen(); + + await waitFor(() => expect(screen.getByText('Damaged Raccoon')).toBeInTheDocument()); + }); +}); + +const asAssignee = (profile: UserProfileWithAvatar): AssigneeWithProfile => ({ + uid: profile.uid, + profile, +}); diff --git a/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx new file mode 100644 index 00000000000000..cb824adf0a2178 --- /dev/null +++ b/x-pack/plugins/cases/public/components/case_view/components/suggest_users_popover.tsx @@ -0,0 +1,144 @@ +/* + * 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, { useCallback, useMemo, useState } from 'react'; +import { UserProfilesPopover, UserProfileWithAvatar } from '@kbn/user-profile-components'; + +import { EuiButtonIcon, EuiToolTip } from '@elastic/eui'; +import { isEmpty } from 'lodash'; +import { useSuggestUserProfiles } from '../../../containers/user_profiles/use_suggest_user_profiles'; +import { useCasesContext } from '../../cases_context/use_cases_context'; +import { AssigneeWithProfile } from '../../user_profiles/types'; +import * as i18n from '../translations'; +import { bringCurrentUserToFrontAndSort } from '../../user_profiles/sort'; +import { SelectedStatusMessage } from '../../user_profiles/selected_status_message'; +import { EmptyMessage } from '../../user_profiles/empty_message'; +import { NoMatches } from '../../user_profiles/no_matches'; +import { CurrentUserProfile } from '../../types'; + +const PopoverButton: React.FC<{ togglePopover: () => void; isDisabled: boolean }> = ({ + togglePopover, + isDisabled, +}) => ( + + + +); +PopoverButton.displayName = 'PopoverButton'; + +export interface SuggestUsersPopoverProps { + assignedUsersWithProfiles: AssigneeWithProfile[]; + currentUserProfile: CurrentUserProfile; + isLoading: boolean; + isPopoverOpen: boolean; + onUsersChange: (users: UserProfileWithAvatar[]) => void; + togglePopover: () => void; + onClosePopover: () => void; +} + +const SuggestUsersPopoverComponent: React.FC = ({ + assignedUsersWithProfiles, + currentUserProfile, + isLoading, + isPopoverOpen, + onUsersChange, + togglePopover, + onClosePopover, +}) => { + const { owner } = useCasesContext(); + const [searchTerm, setSearchTerm] = useState(''); + + const selectedProfiles = useMemo(() => { + return bringCurrentUserToFrontAndSort( + currentUserProfile, + assignedUsersWithProfiles.map((assignee) => ({ ...assignee.profile })) + ); + }, [assignedUsersWithProfiles, currentUserProfile]); + + const [selectedUsers, setSelectedUsers] = useState(); + const [isUserTyping, setIsUserTyping] = useState(false); + + const onChange = useCallback( + (users: UserProfileWithAvatar[]) => { + const sortedUsers = bringCurrentUserToFrontAndSort(currentUserProfile, users); + setSelectedUsers(sortedUsers); + onUsersChange(sortedUsers ?? []); + }, + [currentUserProfile, onUsersChange] + ); + + const selectedStatusMessage = useCallback( + (selectedCount: number) => ( + + ), + [] + ); + + const onDebounce = useCallback(() => setIsUserTyping(false), []); + + const { + data: userProfiles, + isLoading: isLoadingSuggest, + isFetching: isFetchingSuggest, + } = useSuggestUserProfiles({ + name: searchTerm, + owners: owner, + onDebounce, + }); + + const isLoadingData = isLoadingSuggest || isLoading || isFetchingSuggest || isUserTyping; + const isDisabled = isLoading; + + const searchResultProfiles = useMemo( + () => bringCurrentUserToFrontAndSort(currentUserProfile, userProfiles), + [currentUserProfile, userProfiles] + ); + + return ( + } + isOpen={isPopoverOpen} + closePopover={onClosePopover} + panelStyle={{ + minWidth: 520, + }} + selectableProps={{ + onChange, + onSearchChange: (term) => { + setSearchTerm(term); + + if (!isEmpty(term)) { + setIsUserTyping(true); + } + }, + selectedStatusMessage, + options: searchResultProfiles, + selectedOptions: selectedUsers ?? selectedProfiles, + isLoading: isLoadingData, + height: 'full', + searchPlaceholder: i18n.SEARCH_USERS, + clearButtonLabel: i18n.REMOVE_ASSIGNEES, + emptyMessage: , + noMatchesMessage: !isLoadingData ? : , + }} + /> + ); +}; + +SuggestUsersPopoverComponent.displayName = 'SuggestUsersPopover'; + +export const SuggestUsersPopover = React.memo(SuggestUsersPopoverComponent); diff --git a/x-pack/plugins/cases/public/components/user_list/index.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/user_list.test.tsx similarity index 93% rename from x-pack/plugins/cases/public/components/user_list/index.test.tsx rename to x-pack/plugins/cases/public/components/case_view/components/user_list.test.tsx index 70f9e7d2fbdfc6..ab3b0f90c65a6d 100644 --- a/x-pack/plugins/cases/public/components/user_list/index.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/user_list.test.tsx @@ -7,18 +7,20 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { UserList } from '.'; -import * as i18n from '../case_view/translations'; +import { UserList } from './user_list'; +import * as i18n from '../translations'; describe('UserList ', () => { const title = 'Case Title'; const caseLink = 'http://reddit.com'; const user = { username: 'username', fullName: 'Full Name', email: 'testemail@elastic.co' }; const open = jest.fn(); + beforeEach(() => { jest.clearAllMocks(); window.open = open; }); + it('triggers mailto when email icon clicked', () => { const wrapper = shallow( + i18n.translate('xpack.cases.caseView.sendEmalLinkAria', { + values: { user }, + defaultMessage: 'click to send an email to {user}', + }); + +export const EDIT_ASSIGNEES_ARIA_LABEL = i18n.translate( + 'xpack.cases.caseView.editAssigneesAriaLabel', + { + defaultMessage: 'click to edit assignees', + } +); + +export const NO_ASSIGNEES = i18n.translate('xpack.cases.caseView.noAssignees', { + defaultMessage: 'No users have been assigned.', +}); + +export const ASSIGN_A_USER = i18n.translate('xpack.cases.caseView.assignUser', { + defaultMessage: 'Assign a user', +}); + +export const SPACED_OR = i18n.translate('xpack.cases.caseView.spacedOrText', { + defaultMessage: ' or ', +}); + +export const ASSIGN_YOURSELF = i18n.translate('xpack.cases.caseView.assignYourself', { + defaultMessage: 'assign yourself', +}); + +export const TOTAL_USERS_ASSIGNED = (total: number) => + i18n.translate('xpack.cases.caseView.totalUsersAssigned', { + defaultMessage: '{total} assigned', + values: { total }, + }); diff --git a/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts b/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts index 33620c91d87a2d..9180244b9cf456 100644 --- a/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts +++ b/x-pack/plugins/cases/public/components/case_view/use_on_update_field.ts @@ -6,6 +6,8 @@ */ import { useCallback } from 'react'; +import deepEqual from 'fast-deep-equal'; + import { CaseConnector } from '../../../common/api'; import { CaseAttributes } from '../../../common/api/cases/case'; import { CaseStatuses } from '../../../common/api/cases/status'; @@ -68,6 +70,13 @@ export const useOnUpdateField = ({ caseData, caseId }: { caseData: Case; caseId: if (caseData.severity !== value) { callUpdate('severity', severityUpdate); } + break; + case 'assignees': + const assigneesUpdate = getTypedPayload(value); + if (!deepEqual(caseData.assignees, value)) { + callUpdate('assignees', assigneesUpdate); + } + break; default: return null; } diff --git a/x-pack/plugins/cases/public/components/create/assignees.test.tsx b/x-pack/plugins/cases/public/components/create/assignees.test.tsx new file mode 100644 index 00000000000000..2ff593651abf79 --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/assignees.test.tsx @@ -0,0 +1,153 @@ +/* + * 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 userEvent from '@testing-library/user-event'; +import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; + +import { useForm, Form, FormHook } from '../../common/shared_imports'; +import { userProfiles } from '../../containers/user_profiles/api.mock'; +import { Assignees } from './assignees'; +import { FormProps } from './schema'; +import { act, waitFor } from '@testing-library/react'; +import * as api from '../../containers/user_profiles/api'; +import { UserProfile } from '@kbn/user-profile-components'; + +jest.mock('../../containers/user_profiles/api'); + +const currentUserProfile = userProfiles[0]; + +describe('Assignees', () => { + let globalForm: FormHook; + let appMockRender: AppMockRenderer; + + const MockHookWrapperComponent: React.FC = ({ children }) => { + const { form } = useForm(); + globalForm = form; + + return
{children}
; + }; + + beforeEach(() => { + jest.clearAllMocks(); + appMockRender = createAppMockRenderer(); + }); + + it('renders', async () => { + const result = appMockRender.render( + + + + ); + + await waitFor(() => { + expect(result.getByTestId('comboBoxSearchInput')).not.toBeDisabled(); + }); + + expect(result.getByTestId('createCaseAssigneesComboBox')).toBeInTheDocument(); + }); + + it('does not render the assign yourself link when the current user profile is undefined', async () => { + const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); + spyOnGetCurrentUserProfile.mockResolvedValue(undefined as unknown as UserProfile); + + const result = appMockRender.render( + + + + ); + + await waitFor(() => { + expect(result.getByTestId('comboBoxSearchInput')).not.toBeDisabled(); + }); + + expect(result.queryByTestId('create-case-assign-yourself-link')).not.toBeInTheDocument(); + expect(result.getByTestId('createCaseAssigneesComboBox')).toBeInTheDocument(); + }); + + it('selects the current user correctly', async () => { + const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); + spyOnGetCurrentUserProfile.mockResolvedValue(currentUserProfile); + + const result = appMockRender.render( + + + + ); + + await waitFor(() => { + expect(result.getByTestId('comboBoxSearchInput')).not.toBeDisabled(); + }); + + act(() => { + userEvent.click(result.getByTestId('create-case-assign-yourself-link')); + }); + + await waitFor(() => { + expect(globalForm.getFormData()).toEqual({ assignees: [{ uid: currentUserProfile.uid }] }); + }); + }); + + it('disables the assign yourself button if the current user is already selected', async () => { + const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); + spyOnGetCurrentUserProfile.mockResolvedValue(currentUserProfile); + + const result = appMockRender.render( + + + + ); + + await waitFor(() => { + expect(result.getByTestId('comboBoxSearchInput')).not.toBeDisabled(); + }); + + act(() => { + userEvent.click(result.getByTestId('create-case-assign-yourself-link')); + }); + + await waitFor(() => { + expect(globalForm.getFormData()).toEqual({ assignees: [{ uid: currentUserProfile.uid }] }); + }); + + expect(result.getByTestId('create-case-assign-yourself-link')).toBeDisabled(); + }); + + it('assignees users correctly', async () => { + const result = appMockRender.render( + + + + ); + + await waitFor(() => { + expect(result.getByTestId('comboBoxSearchInput')).not.toBeDisabled(); + }); + + await act(async () => { + await userEvent.type(result.getByTestId('comboBoxSearchInput'), 'dr', { delay: 1 }); + }); + + await waitFor(() => { + expect( + result.getByTestId('comboBoxOptionsList createCaseAssigneesComboBox-optionsList') + ).toBeInTheDocument(); + }); + + await waitFor(async () => { + expect(result.getByText(`${currentUserProfile.user.full_name}`)).toBeInTheDocument(); + }); + + act(() => { + userEvent.click(result.getByText(`${currentUserProfile.user.full_name}`)); + }); + + await waitFor(() => { + expect(globalForm.getFormData()).toEqual({ assignees: [{ uid: currentUserProfile.uid }] }); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/components/create/assignees.tsx b/x-pack/plugins/cases/public/components/create/assignees.tsx new file mode 100644 index 00000000000000..be4efc0edfed9a --- /dev/null +++ b/x-pack/plugins/cases/public/components/create/assignees.tsx @@ -0,0 +1,225 @@ +/* + * 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 { isEmpty } from 'lodash'; +import React, { memo, useCallback, useState } from 'react'; +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFormRow, + EuiLink, + EuiSelectableListItem, + EuiTextColor, +} from '@elastic/eui'; +import { + UserProfileWithAvatar, + UserAvatar, + getUserDisplayName, + UserProfile, +} from '@kbn/user-profile-components'; +import { UseField, FieldConfig, FieldHook } from '../../common/shared_imports'; +import { useSuggestUserProfiles } from '../../containers/user_profiles/use_suggest_user_profiles'; +import { useCasesContext } from '../cases_context/use_cases_context'; +import { useGetCurrentUserProfile } from '../../containers/user_profiles/use_get_current_user_profile'; +import { OptionalFieldLabel } from './optional_field_label'; +import * as i18n from './translations'; +import { bringCurrentUserToFrontAndSort } from '../user_profiles/sort'; +import { useAvailableCasesOwners } from '../app/use_available_owners'; +import { getAllPermissionsExceptFrom } from '../../utils/permissions'; + +interface Props { + isLoading: boolean; +} + +interface FieldProps { + field: FieldHook; + options: EuiComboBoxOptionOption[]; + isLoading: boolean; + isDisabled: boolean; + currentUserProfile?: UserProfile; + selectedOptions: EuiComboBoxOptionOption[]; + setSelectedOptions: React.Dispatch>; + onSearchComboChange: (value: string) => void; +} + +const getConfig = (): FieldConfig => ({ + label: i18n.ASSIGNEES, + defaultValue: [], +}); + +const userProfileToComboBoxOption = (userProfile: UserProfileWithAvatar) => ({ + label: getUserDisplayName(userProfile.user), + value: userProfile.uid, + user: userProfile.user, + data: userProfile.data, +}); + +const comboBoxOptionToAssignee = (option: EuiComboBoxOptionOption) => ({ uid: option.value }); + +const AssigneesFieldComponent: React.FC = React.memo( + ({ + field, + isLoading, + isDisabled, + options, + currentUserProfile, + selectedOptions, + setSelectedOptions, + onSearchComboChange, + }) => { + const { setValue } = field; + + const onComboChange = useCallback( + (currentOptions: EuiComboBoxOptionOption[]) => { + setSelectedOptions(currentOptions); + setValue(currentOptions.map((option) => comboBoxOptionToAssignee(option))); + }, + [setSelectedOptions, setValue] + ); + + const onSelfAssign = useCallback(() => { + if (!currentUserProfile) { + return; + } + + setSelectedOptions((prev) => [ + ...(prev ?? []), + userProfileToComboBoxOption(currentUserProfile), + ]); + + setValue([ + ...(selectedOptions?.map((option) => comboBoxOptionToAssignee(option)) ?? []), + { uid: currentUserProfile.uid }, + ]); + }, [currentUserProfile, selectedOptions, setSelectedOptions, setValue]); + + const renderOption = useCallback( + (option: EuiComboBoxOptionOption, searchValue: string, contentClassName: string) => { + const { user, data, value } = option as EuiComboBoxOptionOption & + UserProfileWithAvatar; + + return ( + } + className={contentClassName} + append={{user.email}} + > + {getUserDisplayName(user)} + + ); + }, + [] + ); + + const isCurrentUserSelected = Boolean( + selectedOptions?.find((option) => option.value === currentUserProfile?.uid) + ); + + return ( + + {i18n.ASSIGN_YOURSELF} + + ) : undefined + } + > + + + ); + } +); + +AssigneesFieldComponent.displayName = 'AssigneesFieldComponent'; + +const AssigneesComponent: React.FC = ({ isLoading: isLoadingForm }) => { + const { owner: owners } = useCasesContext(); + const availableOwners = useAvailableCasesOwners(getAllPermissionsExceptFrom('delete')); + const [searchTerm, setSearchTerm] = useState(''); + const [selectedOptions, setSelectedOptions] = useState(); + const [isUserTyping, setIsUserTyping] = useState(false); + const hasOwners = owners.length > 0; + + const { data: currentUserProfile, isLoading: isLoadingCurrentUserProfile } = + useGetCurrentUserProfile(); + + const onDebounce = useCallback(() => setIsUserTyping(false), []); + + const { + data: userProfiles, + isLoading: isLoadingSuggest, + isFetching: isFetchingSuggest, + } = useSuggestUserProfiles({ + name: searchTerm, + owners: hasOwners ? owners : availableOwners, + onDebounce, + }); + + const options = + bringCurrentUserToFrontAndSort(currentUserProfile, userProfiles)?.map((userProfile) => + userProfileToComboBoxOption(userProfile) + ) ?? []; + + const onSearchComboChange = (value: string) => { + if (!isEmpty(value)) { + setSearchTerm(value); + setIsUserTyping(true); + } + }; + + const isLoading = + isLoadingForm || + isLoadingCurrentUserProfile || + isLoadingSuggest || + isFetchingSuggest || + isUserTyping; + + const isDisabled = isLoadingForm || isLoadingCurrentUserProfile; + + return ( + + ); +}; + +AssigneesComponent.displayName = 'AssigneesComponent'; + +export const Assignees = memo(AssigneesComponent); diff --git a/x-pack/plugins/cases/public/components/create/form.tsx b/x-pack/plugins/cases/public/components/create/form.tsx index 78f5a4e9d5c54d..d34e216c34af93 100644 --- a/x-pack/plugins/cases/public/components/create/form.tsx +++ b/x-pack/plugins/cases/public/components/create/form.tsx @@ -36,6 +36,7 @@ import { useCasesContext } from '../cases_context/use_cases_context'; import { useAvailableCasesOwners } from '../app/use_available_owners'; import { CaseAttachmentsWithoutOwner } from '../../types'; import { Severity } from './severity'; +import { Assignees } from './assignees'; interface ContainerProps { big?: boolean; @@ -86,6 +87,9 @@ export const CreateCaseFormFields: React.FC = React.m children: ( <> + <Container> + <Assignees isLoading={isSubmitting} /> + </Container> <Container> <Tags isLoading={isSubmitting} /> </Container> diff --git a/x-pack/plugins/cases/public/components/create/form_context.test.tsx b/x-pack/plugins/cases/public/components/create/form_context.test.tsx index 6d8520e61a4938..8b45258889e5c0 100644 --- a/x-pack/plugins/cases/public/components/create/form_context.test.tsx +++ b/x-pack/plugins/cases/public/components/create/form_context.test.tsx @@ -6,14 +6,12 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; import { act, RenderResult, waitFor, within } from '@testing-library/react'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { CaseSeverity, CommentType, ConnectorTypes } from '../../../common/api'; import { useKibana } from '../../common/lib/kibana'; -import { AppMockRenderer, createAppMockRenderer, TestProviders } from '../../common/mock'; +import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; import { usePostCase } from '../../containers/use_post_case'; import { useCreateAttachments } from '../../containers/use_create_attachments'; import { useCaseConfigure } from '../../containers/configure/use_configure'; @@ -43,6 +41,8 @@ import { connectorsMock } from '../../common/mock/connectors'; import { CaseAttachments } from '../../types'; import { useGetConnectors } from '../../containers/configure/use_connectors'; import { useGetTags } from '../../containers/use_get_tags'; +import { waitForComponentToUpdate } from '../../common/test_utils'; +import { userProfiles } from '../../containers/user_profiles/api.mock'; const sampleId = 'case-id'; @@ -60,6 +60,7 @@ jest.mock('../connectors/jira/use_get_single_issue'); jest.mock('../connectors/jira/use_get_issues'); jest.mock('../connectors/servicenow/use_get_choices'); jest.mock('../../common/lib/kibana'); +jest.mock('../../containers/user_profiles/api'); const useGetConnectorsMock = useGetConnectors as jest.Mock; const useCaseConfigureMock = useCaseConfigure as jest.Mock; @@ -93,37 +94,21 @@ const defaultPostPushToService = { pushCaseToExternalService, }; -const fillForm = (wrapper: ReactWrapper) => { - wrapper - .find(`[data-test-subj="caseTitle"] input`) - .first() - .simulate('change', { target: { value: sampleData.title } }); - - wrapper - .find(`[data-test-subj="caseDescription"] textarea`) - .first() - .simulate('change', { target: { value: sampleData.description } }); - - act(() => { - ( - wrapper.find(EuiComboBox).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange(sampleTags.map((tag) => ({ label: tag }))); - }); -}; - const fillFormReactTestingLib = async (renderResult: RenderResult) => { const titleInput = within(renderResult.getByTestId('caseTitle')).getByTestId('input'); + userEvent.type(titleInput, sampleData.title); const descriptionInput = renderResult.container.querySelector( `[data-test-subj="caseDescription"] textarea` ); + if (descriptionInput) { userEvent.type(descriptionInput, sampleData.description); } + const caseTags = renderResult.getByTestId('caseTags'); + for (let i = 0; i < sampleTags.length; i++) { const tagsInput = await within(caseTags).findByTestId('comboBoxInput'); userEvent.type(tagsInput, `${sampleTags[i]}{enter}`); @@ -185,6 +170,7 @@ describe('Create case', () => { expect(renderResult.getByTestId('caseTitle')).toBeTruthy(); expect(renderResult.getByTestId('caseSeverity')).toBeTruthy(); expect(renderResult.getByTestId('caseDescription')).toBeTruthy(); + expect(renderResult.getByTestId('createCaseAssigneesComboBox')).toBeTruthy(); expect(renderResult.getByTestId('caseTags')).toBeTruthy(); expect(renderResult.getByTestId('caseConnectors')).toBeTruthy(); expect(renderResult.getByTestId('case-creation-form-steps')).toBeTruthy(); @@ -241,31 +227,30 @@ describe('Create case', () => { it('does not submits the title when the length is longer than 64 characters', async () => { const longTitle = - 'This is a title that should not be saved as it is longer than 64 characters.'; - - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + 'This is a title that should not be saved as it is longer than 64 characters.{enter}'; + + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); + await act(async () => { + const titleInput = within(renderResult.getByTestId('caseTitle')).getByTestId('input'); + await userEvent.type(titleInput, longTitle, { delay: 1 }); + }); + act(() => { - wrapper - .find(`[data-test-subj="caseTitle"] input`) - .first() - .simulate('change', { target: { value: longTitle } }); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + userEvent.click(renderResult.getByTestId('create-case-submit')); }); await waitFor(() => { - wrapper.update(); - expect(wrapper.find('[data-test-subj="caseTitle"] .euiFormErrorText').text()).toBe( - 'The length of the title is too long. The maximum length is 64.' - ); + expect( + renderResult.getByText('The length of the title is too long. The maximum length is 64.') + ).toBeInTheDocument(); }); + expect(postCase).not.toHaveBeenCalled(); }); @@ -275,18 +260,25 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - wrapper.find('[data-test-subj="caseSyncAlerts"] button').first().simulate('click'); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + await fillFormReactTestingLib(renderResult); + + act(() => { + const syncAlertsButton = within(renderResult.getByTestId('caseSyncAlerts')).getByTestId( + 'input' + ); + userEvent.click(syncAlertsButton); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); await waitFor(() => expect(postCase).toBeCalledWith({ ...sampleData, settings: { syncAlerts: false } }) @@ -294,22 +286,25 @@ describe('Create case', () => { }); it('should set sync alerts to false when the sync feature setting is false', async () => { + mockedContext = createAppMockRenderer({ + features: { alerts: { sync: false, enabled: true } }, + }); useGetConnectorsMock.mockReturnValue({ ...sampleConnectorData, data: connectorsMock, }); - const wrapper = mount( - <TestProviders features={{ alerts: { sync: false, enabled: true } }}> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + await fillFormReactTestingLib(renderResult); + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); await waitFor(() => expect(postCase).toBeCalledWith({ ...sampleData, settings: { syncAlerts: false } }) @@ -345,18 +340,16 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - await act(async () => { - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + await fillFormReactTestingLib(renderResult); + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); }); await waitFor(() => @@ -395,17 +388,17 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + await fillFormReactTestingLib(renderResult); + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); await waitFor(() => { expect(postCase).toBeCalledWith(sampleData); expect(pushCaseToExternalService).not.toHaveBeenCalled(); @@ -420,40 +413,43 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - expect(wrapper.find(`[data-test-subj="connector-fields-jira"]`).exists()).toBeFalsy(); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.find(`button[data-test-subj="dropdown-connector-jira-1"]`).simulate('click'); + await fillFormReactTestingLib(renderResult); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connectors')); + }); await waitFor(() => { - wrapper.update(); - expect(wrapper.find(`[data-test-subj="connector-fields-jira"]`).exists()).toBeTruthy(); + expect(renderResult.getByTestId('dropdown-connector-jira-1')).toBeInTheDocument(); }); - wrapper - .find('select[data-test-subj="issueTypeSelect"]') - .first() - .simulate('change', { - target: { value: '10007' }, - }); + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connector-jira-1')); + }); - wrapper - .find('select[data-test-subj="prioritySelect"]') - .first() - .simulate('change', { - target: { value: '2' }, - }); + await waitFor(() => { + expect(renderResult.getByTestId('issueTypeSelect')).toBeInTheDocument(); + expect(renderResult.getByTestId('prioritySelect')).toBeInTheDocument(); + }); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + act(() => { + userEvent.selectOptions(renderResult.getByTestId('issueTypeSelect'), ['10007']); + }); + + act(() => { + userEvent.selectOptions(renderResult.getByTestId('prioritySelect'), ['Low']); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); await waitFor(() => { expect(postCase).toBeCalledWith({ @@ -462,7 +458,7 @@ describe('Create case', () => { id: 'jira-1', name: 'Jira', type: '.jira', - fields: { issueType: '10007', parent: null, priority: '2' }, + fields: { issueType: '10007', parent: null, priority: 'Low' }, }, }); expect(pushCaseToExternalService).toHaveBeenCalledWith({ @@ -471,7 +467,7 @@ describe('Create case', () => { id: 'jira-1', name: 'Jira', type: '.jira', - fields: { issueType: '10007', parent: null, priority: '2' }, + fields: { issueType: '10007', parent: null, priority: 'Low' }, }, }); expect(onFormSubmitSuccess).toHaveBeenCalledWith({ @@ -487,41 +483,49 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - expect(wrapper.find(`[data-test-subj="connector-fields-resilient"]`).exists()).toBeFalsy(); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.find(`button[data-test-subj="dropdown-connector-resilient-2"]`).simulate('click'); + await fillFormReactTestingLib(renderResult); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connectors')); + }); await waitFor(() => { - wrapper.update(); - expect(wrapper.find(`[data-test-subj="connector-fields-resilient"]`).exists()).toBeTruthy(); + expect(renderResult.getByTestId('dropdown-connector-resilient-2')).toBeInTheDocument(); }); act(() => { - ( - wrapper.find(EuiComboBox).at(1).props() as unknown as { - onChange: (a: EuiComboBoxOptionOption[]) => void; - } - ).onChange([{ value: '19', label: 'Denial of Service' }]); - }); - - wrapper - .find('select[data-test-subj="severitySelect"]') - .first() - .simulate('change', { - target: { value: '4' }, + userEvent.click(renderResult.getByTestId('dropdown-connector-resilient-2')); + }); + + await waitFor(() => { + expect(renderResult.getByTestId('incidentTypeComboBox')).toBeInTheDocument(); + expect(renderResult.getByTestId('severitySelect')).toBeInTheDocument(); + }); + + const checkbox = within(renderResult.getByTestId('incidentTypeComboBox')).getByTestId( + 'comboBoxSearchInput' + ); + + await act(async () => { + await userEvent.type(checkbox, 'Denial of Service{enter}', { + delay: 2, }); + }); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + act(() => { + userEvent.selectOptions(renderResult.getByTestId('severitySelect'), ['4']); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); await waitFor(() => { expect(postCase).toBeCalledWith({ @@ -530,7 +534,7 @@ describe('Create case', () => { id: 'resilient-2', name: 'My Connector 2', type: '.resilient', - fields: { incidentTypes: ['19'], severityCode: '4' }, + fields: { incidentTypes: ['21'], severityCode: '4' }, }, }); @@ -540,7 +544,7 @@ describe('Create case', () => { id: 'resilient-2', name: 'My Connector 2', type: '.resilient', - fields: { incidentTypes: ['19'], severityCode: '4' }, + fields: { incidentTypes: ['21'], severityCode: '4' }, }, }); @@ -557,54 +561,53 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - expect(wrapper.find(`[data-test-subj="connector-fields-sn-itsm"]`).exists()).toBeFalsy(); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.find(`button[data-test-subj="dropdown-connector-servicenow-1"]`).simulate('click'); + await fillFormReactTestingLib(renderResult); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connectors')); + }); await waitFor(() => { - wrapper.update(); - expect(wrapper.find(`[data-test-subj="connector-fields-sn-itsm"]`).exists()).toBeTruthy(); + expect(renderResult.getByTestId('dropdown-connector-servicenow-1')).toBeInTheDocument(); }); - // we need the choices response to conditionally show the subcategory select + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connector-servicenow-1')); + }); + + await waitFor(() => { + expect(onChoicesSuccess).toBeDefined(); + }); + + // // we need the choices response to conditionally show the subcategory select act(() => { onChoicesSuccess(useGetChoicesResponse.choices); }); ['severitySelect', 'urgencySelect', 'impactSelect'].forEach((subj) => { - wrapper - .find(`select[data-test-subj="${subj}"]`) - .first() - .simulate('change', { - target: { value: '2' }, - }); - }); - - wrapper - .find('select[data-test-subj="categorySelect"]') - .first() - .simulate('change', { - target: { value: 'software' }, + act(() => { + userEvent.selectOptions(renderResult.getByTestId(subj), ['2']); }); + }); - wrapper - .find('select[data-test-subj="subcategorySelect"]') - .first() - .simulate('change', { - target: { value: 'os' }, - }); + act(() => { + userEvent.selectOptions(renderResult.getByTestId('categorySelect'), ['software']); + }); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + act(() => { + userEvent.selectOptions(renderResult.getByTestId('subcategorySelect'), ['os']); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); await waitFor(() => { expect(postCase).toBeCalledWith({ @@ -652,23 +655,29 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mount( - <TestProviders> - <FormContext onSuccess={onFormSubmitSuccess}> - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - expect(wrapper.find(`[data-test-subj="connector-fields-sn-sir"]`).exists()).toBeFalsy(); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.find(`button[data-test-subj="dropdown-connector-servicenow-sir"]`).simulate('click'); + await fillFormReactTestingLib(renderResult); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connectors')); + }); + + await waitFor(() => { + expect(renderResult.getByTestId('dropdown-connector-servicenow-sir')).toBeInTheDocument(); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connector-servicenow-sir')); + }); await waitFor(() => { - wrapper.update(); - expect(wrapper.find(`[data-test-subj="connector-fields-sn-sir"]`).exists()).toBeTruthy(); + expect(onChoicesSuccess).toBeDefined(); }); // we need the choices response to conditionally show the subcategory select @@ -676,33 +685,25 @@ describe('Create case', () => { onChoicesSuccess(useGetChoicesResponse.choices); }); - wrapper - .find('[data-test-subj="destIpCheckbox"] input') - .first() - .simulate('change', { target: { checked: false } }); + act(() => { + userEvent.click(renderResult.getByTestId('destIpCheckbox')); + }); - wrapper - .find('select[data-test-subj="prioritySelect"]') - .first() - .simulate('change', { - target: { value: '1' }, - }); + act(() => { + userEvent.selectOptions(renderResult.getByTestId('prioritySelect'), ['1']); + }); - wrapper - .find('select[data-test-subj="categorySelect"]') - .first() - .simulate('change', { - target: { value: 'Denial of Service' }, - }); + act(() => { + userEvent.selectOptions(renderResult.getByTestId('categorySelect'), ['Denial of Service']); + }); - wrapper - .find('select[data-test-subj="subcategorySelect"]') - .first() - .simulate('change', { - target: { value: '26' }, - }); + act(() => { + userEvent.selectOptions(renderResult.getByTestId('subcategorySelect'), ['26']); + }); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); await waitFor(() => { expect(postCase).toBeCalledWith({ @@ -755,23 +756,31 @@ describe('Create case', () => { data: connectorsMock, }); - const wrapper = mockedContext.render( + const renderResult = mockedContext.render( <FormContext onSuccess={onFormSubmitSuccess} afterCaseCreated={afterCaseCreated}> <CreateCaseFormFields {...defaultCreateCaseForm} /> <SubmitCaseButton /> </FormContext> ); - await fillFormReactTestingLib(wrapper); - expect(wrapper.queryByTestId('connector-fields-jira')).toBeFalsy(); - userEvent.click(wrapper.getByTestId('dropdown-connectors')); - await waitForEuiPopoverOpen(); - await act(async () => { - userEvent.click(wrapper.getByTestId('dropdown-connector-jira-1')); + await fillFormReactTestingLib(renderResult); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connectors')); + }); + + await waitFor(() => { + expect(renderResult.getByTestId('dropdown-connector-jira-1')).toBeInTheDocument(); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connector-jira-1')); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); }); - expect(wrapper.getByTestId('connector-fields-jira')).toBeTruthy(); - userEvent.click(wrapper.getByTestId('create-case-submit')); await waitFor(() => { expect(afterCaseCreated).toHaveBeenCalledWith( { @@ -811,19 +820,21 @@ describe('Create case', () => { }, ]; - const wrapper = mockedContext.render( + const renderResult = mockedContext.render( <FormContext onSuccess={onFormSubmitSuccess} attachments={attachments}> <CreateCaseFormFields {...defaultCreateCaseForm} /> <SubmitCaseButton /> </FormContext> ); - await fillFormReactTestingLib(wrapper); + await fillFormReactTestingLib(renderResult); - await act(async () => { - userEvent.click(wrapper.getByTestId('create-case-submit')); + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); }); + await waitForComponentToUpdate(); + expect(createAttachments).toHaveBeenCalledTimes(1); expect(createAttachments).toHaveBeenCalledWith({ caseId: 'case-id', @@ -839,19 +850,21 @@ describe('Create case', () => { }); const attachments: CaseAttachments = []; - const wrapper = mockedContext.render( + const renderResult = mockedContext.render( <FormContext onSuccess={onFormSubmitSuccess} attachments={attachments}> <CreateCaseFormFields {...defaultCreateCaseForm} /> <SubmitCaseButton /> </FormContext> ); - await fillFormReactTestingLib(wrapper); + await fillFormReactTestingLib(renderResult); - await act(async () => { - userEvent.click(wrapper.getByTestId('create-case-submit')); + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); }); + await waitForComponentToUpdate(); + expect(createAttachments).not.toHaveBeenCalled(); }); @@ -873,30 +886,35 @@ describe('Create case', () => { }, ]; - const wrapper = mount( - <TestProviders> - <FormContext - onSuccess={onFormSubmitSuccess} - afterCaseCreated={afterCaseCreated} - attachments={attachments} - > - <CreateCaseFormFields {...defaultCreateCaseForm} /> - <SubmitCaseButton /> - </FormContext> - </TestProviders> + const renderResult = mockedContext.render( + <FormContext + onSuccess={onFormSubmitSuccess} + afterCaseCreated={afterCaseCreated} + attachments={attachments} + > + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> ); - fillForm(wrapper); - expect(wrapper.find(`[data-test-subj="connector-fields-jira"]`).exists()).toBeFalsy(); - wrapper.find('button[data-test-subj="dropdown-connectors"]').simulate('click'); - wrapper.find(`button[data-test-subj="dropdown-connector-jira-1"]`).simulate('click'); + await fillFormReactTestingLib(renderResult); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connectors')); + }); await waitFor(() => { - wrapper.update(); - expect(wrapper.find(`[data-test-subj="connector-fields-jira"]`).exists()).toBeTruthy(); + expect(renderResult.getByTestId('dropdown-connector-jira-1')).toBeInTheDocument(); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('dropdown-connector-jira-1')); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); }); - wrapper.find(`[data-test-subj="create-case-submit"]`).first().simulate('click'); await waitFor(() => { expect(postCase).toHaveBeenCalled(); expect(createAttachments).toHaveBeenCalled(); @@ -933,9 +951,7 @@ describe('Create case', () => { </FormContext> ); - await act(async () => { - fillFormReactTestingLib(result); - }); + await fillFormReactTestingLib(result); await act(async () => { userEvent.click(result.getByTestId('create-case-submit')); @@ -944,4 +960,54 @@ describe('Create case', () => { expect(pushCaseToExternalService).not.toHaveBeenCalled(); }); }); + + describe('Assignees', () => { + it('should submit assignees', async () => { + const renderResult = mockedContext.render( + <FormContext onSuccess={onFormSubmitSuccess}> + <CreateCaseFormFields {...defaultCreateCaseForm} /> + <SubmitCaseButton /> + </FormContext> + ); + + await fillFormReactTestingLib(renderResult); + + const assigneesComboBox = within(renderResult.getByTestId('createCaseAssigneesComboBox')); + + await waitFor(() => { + expect(assigneesComboBox.getByTestId('comboBoxSearchInput')).not.toBeDisabled(); + }); + + await act(async () => { + await userEvent.type(assigneesComboBox.getByTestId('comboBoxSearchInput'), 'dr', { + delay: 1, + }); + }); + + await waitFor(() => { + expect( + renderResult.getByTestId('comboBoxOptionsList createCaseAssigneesComboBox-optionsList') + ).toBeInTheDocument(); + }); + + await waitFor(async () => { + expect(renderResult.getByText(`${userProfiles[0].user.full_name}`)).toBeInTheDocument(); + }); + + act(() => { + userEvent.click(renderResult.getByText(`${userProfiles[0].user.full_name}`)); + }); + + act(() => { + userEvent.click(renderResult.getByTestId('create-case-submit')); + }); + + await waitForComponentToUpdate(); + + expect(postCase).toBeCalledWith({ + ...sampleData, + assignees: [{ uid: userProfiles[0].uid }], + }); + }); + }); }); diff --git a/x-pack/plugins/cases/public/components/create/index.test.tsx b/x-pack/plugins/cases/public/components/create/index.test.tsx index c455ae0c3628de..ee2d2d9a4468c5 100644 --- a/x-pack/plugins/cases/public/components/create/index.test.tsx +++ b/x-pack/plugins/cases/public/components/create/index.test.tsx @@ -31,6 +31,7 @@ import { useGetConnectors } from '../../containers/configure/use_connectors'; import { useGetTags } from '../../containers/use_get_tags'; jest.mock('../../containers/api'); +jest.mock('../../containers/user_profiles/api'); jest.mock('../../containers/use_get_tags'); jest.mock('../../containers/configure/use_connectors'); jest.mock('../../containers/configure/use_configure'); @@ -63,7 +64,7 @@ const fillForm = (wrapper: ReactWrapper) => { act(() => { ( - wrapper.find(EuiComboBox).props() as unknown as { + wrapper.find(EuiComboBox).at(1).props() as unknown as { onChange: (a: EuiComboBoxOptionOption[]) => void; } ).onChange(sampleTags.map((tag) => ({ label: tag }))); diff --git a/x-pack/plugins/cases/public/components/create/mock.ts b/x-pack/plugins/cases/public/components/create/mock.ts index 8f67b3c05d3e41..c54e3206b2b016 100644 --- a/x-pack/plugins/cases/public/components/create/mock.ts +++ b/x-pack/plugins/cases/public/components/create/mock.ts @@ -25,6 +25,7 @@ export const sampleData: CasePostRequest = { syncAlerts: true, }, owner: SECURITY_SOLUTION_OWNER, + assignees: [], }; export const sampleConnectorData = { isLoading: false, data: [] }; diff --git a/x-pack/plugins/cases/public/components/create/schema.tsx b/x-pack/plugins/cases/public/components/create/schema.tsx index d72b1cc523f0df..59cf8f919606b1 100644 --- a/x-pack/plugins/cases/public/components/create/schema.tsx +++ b/x-pack/plugins/cases/public/components/create/schema.tsx @@ -100,4 +100,5 @@ export const schema: FormSchema<FormProps> = { type: FIELD_TYPES.TOGGLE, defaultValue: true, }, + assignees: {}, }; diff --git a/x-pack/plugins/cases/public/components/create/translations.ts b/x-pack/plugins/cases/public/components/create/translations.ts index 7e0f7e5a6b9d58..780a1bbd1d02fc 100644 --- a/x-pack/plugins/cases/public/components/create/translations.ts +++ b/x-pack/plugins/cases/public/components/create/translations.ts @@ -8,6 +8,7 @@ import { i18n } from '@kbn/i18n'; export * from '../../common/translations'; +export * from '../user_profiles/translations'; export const STEP_ONE_TITLE = i18n.translate('xpack.cases.create.stepOneTitle', { defaultMessage: 'Case fields', @@ -24,3 +25,7 @@ export const STEP_THREE_TITLE = i18n.translate('xpack.cases.create.stepThreeTitl export const SYNC_ALERTS_LABEL = i18n.translate('xpack.cases.create.syncAlertsLabel', { defaultMessage: 'Sync alert status with case status', }); + +export const ASSIGN_YOURSELF = i18n.translate('xpack.cases.create.assignYourself', { + defaultMessage: 'Assign yourself', +}); diff --git a/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx b/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx index 3d7be7f08084d0..5db400203468a0 100644 --- a/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx +++ b/x-pack/plugins/cases/public/components/edit_connector/index.test.tsx @@ -219,21 +219,13 @@ describe('EditConnector ', () => { expect(wrapper.find(`[data-test-subj="has-data-to-push-button"]`).exists()).toBeFalsy(); }); - it('displays the callout message when none is selected', async () => { + it('display the callout message when none is selected', async () => { const defaultProps = getDefaultProps(); const props = { ...defaultProps, connectors: [] }; - const wrapper = mount( - <TestProviders> - <EditConnector {...props} /> - </TestProviders> - ); - wrapper.update(); - await waitFor(() => { - expect(true).toBeTruthy(); - }); - wrapper.update(); + const result = appMockRender.render(<EditConnector {...props} />); + await waitFor(() => { - expect(wrapper.find(`[data-test-subj="push-callouts"]`).exists()).toEqual(true); + expect(result.getByTestId('push-callouts')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/cases/public/components/header_page/__snapshots__/editable_title.test.tsx.snap b/x-pack/plugins/cases/public/components/header_page/__snapshots__/editable_title.test.tsx.snap deleted file mode 100644 index 73f466aeec7710..00000000000000 --- a/x-pack/plugins/cases/public/components/header_page/__snapshots__/editable_title.test.tsx.snap +++ /dev/null @@ -1,98 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`EditableTitle renders 1`] = ` -<I18nProvider> - <Component> - <ThemeProvider - theme={[Function]} - > - <QueryClientProvider - client={ - QueryClient { - "defaultOptions": Object { - "queries": Object { - "retry": false, - }, - }, - "logger": BufferedConsole { - "Console": [Function], - "_buffer": Array [], - "_counters": Object {}, - "_groupDepth": 0, - "_timers": Object {}, - "assert": [Function], - "clear": [Function], - "count": [Function], - "countReset": [Function], - "debug": [Function], - "dir": [Function], - "dirxml": [Function], - "error": [Function], - "group": [Function], - "groupCollapsed": [Function], - "groupEnd": [Function], - "info": [Function], - "log": [Function], - "table": [Function], - "time": [Function], - "timeEnd": [Function], - "timeLog": [Function], - "trace": [Function], - "warn": [Function], - }, - "mutationCache": MutationCache { - "config": Object {}, - "listeners": Array [], - "mutationId": 0, - "mutations": Array [], - "subscribe": [Function], - }, - "mutationDefaults": Array [], - "queryCache": QueryCache { - "config": Object {}, - "listeners": Array [], - "queries": Array [], - "queriesMap": Object {}, - "subscribe": [Function], - }, - "queryDefaults": Array [], - } - } - > - <CasesProvider - value={ - Object { - "externalReferenceAttachmentTypeRegistry": ExternalReferenceAttachmentTypeRegistry { - "collection": Map {}, - "name": "ExternalReferenceAttachmentTypeRegistry", - }, - "features": undefined, - "owner": Array [ - "securitySolution", - ], - "permissions": Object { - "all": true, - "create": true, - "delete": true, - "push": true, - "read": true, - "update": true, - }, - "persistableStateAttachmentTypeRegistry": PersistableStateAttachmentTypeRegistry { - "collection": Map {}, - "name": "PersistableStateAttachmentTypeRegistry", - }, - } - } - > - <Memo(EditableTitle) - isLoading={false} - onSubmit={[MockFunction]} - title="Test title" - /> - </CasesProvider> - </QueryClientProvider> - </ThemeProvider> - </Component> -</I18nProvider> -`; diff --git a/x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap b/x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 7e6d9e2b05d94b..00000000000000 --- a/x-pack/plugins/cases/public/components/header_page/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,103 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`HeaderPage it renders 1`] = ` -<I18nProvider> - <Component> - <ThemeProvider - theme={[Function]} - > - <QueryClientProvider - client={ - QueryClient { - "defaultOptions": Object { - "queries": Object { - "retry": false, - }, - }, - "logger": BufferedConsole { - "Console": [Function], - "_buffer": Array [], - "_counters": Object {}, - "_groupDepth": 0, - "_timers": Object {}, - "assert": [Function], - "clear": [Function], - "count": [Function], - "countReset": [Function], - "debug": [Function], - "dir": [Function], - "dirxml": [Function], - "error": [Function], - "group": [Function], - "groupCollapsed": [Function], - "groupEnd": [Function], - "info": [Function], - "log": [Function], - "table": [Function], - "time": [Function], - "timeEnd": [Function], - "timeLog": [Function], - "trace": [Function], - "warn": [Function], - }, - "mutationCache": MutationCache { - "config": Object {}, - "listeners": Array [], - "mutationId": 0, - "mutations": Array [], - "subscribe": [Function], - }, - "mutationDefaults": Array [], - "queryCache": QueryCache { - "config": Object {}, - "listeners": Array [], - "queries": Array [], - "queriesMap": Object {}, - "subscribe": [Function], - }, - "queryDefaults": Array [], - } - } - > - <CasesProvider - value={ - Object { - "externalReferenceAttachmentTypeRegistry": ExternalReferenceAttachmentTypeRegistry { - "collection": Map {}, - "name": "ExternalReferenceAttachmentTypeRegistry", - }, - "features": undefined, - "owner": Array [ - "securitySolution", - ], - "permissions": Object { - "all": true, - "create": true, - "delete": true, - "push": true, - "read": true, - "update": true, - }, - "persistableStateAttachmentTypeRegistry": PersistableStateAttachmentTypeRegistry { - "collection": Map {}, - "name": "PersistableStateAttachmentTypeRegistry", - }, - } - } - > - <Memo(HeaderPage) - border={true} - subtitle="Test subtitle" - subtitle2="Test subtitle 2" - title="Test title" - > - <p> - Test supplement - </p> - </Memo(HeaderPage)> - </CasesProvider> - </QueryClientProvider> - </ThemeProvider> - </Component> -</I18nProvider> -`; diff --git a/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx b/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx index f36996c0134716..e2893cbbc5aa8d 100644 --- a/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx +++ b/x-pack/plugins/cases/public/components/header_page/editable_title.test.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { shallow } from 'enzyme'; import React from 'react'; import '../../common/mock/match_media'; @@ -27,18 +26,16 @@ describe('EditableTitle', () => { isLoading: false, }; + let appMock: AppMockRenderer; + beforeEach(() => { jest.clearAllMocks(); + appMock = createAppMockRenderer(); }); it('renders', () => { - const wrapper = shallow( - <TestProviders> - <EditableTitle {...defaultProps} /> - </TestProviders> - ); - - expect(wrapper).toMatchSnapshot(); + const renderResult = appMock.render(<EditableTitle {...defaultProps} />); + expect(renderResult.getByText('Test title')).toBeInTheDocument(); }); it('does not show the edit icon when the user does not have edit permissions', () => { @@ -269,12 +266,6 @@ describe('EditableTitle', () => { }); describe('Badges', () => { - let appMock: AppMockRenderer; - - beforeEach(() => { - appMock = createAppMockRenderer(); - }); - it('does not render the badge if the release is ga', () => { const renderResult = appMock.render(<EditableTitle {...defaultProps} />); diff --git a/x-pack/plugins/cases/public/components/header_page/index.test.tsx b/x-pack/plugins/cases/public/components/header_page/index.test.tsx index 707cb9b7c43352..c5c7ddcaab8759 100644 --- a/x-pack/plugins/cases/public/components/header_page/index.test.tsx +++ b/x-pack/plugins/cases/public/components/header_page/index.test.tsx @@ -6,7 +6,6 @@ */ import { euiDarkVars } from '@kbn/ui-theme'; -import { shallow } from 'enzyme'; import React from 'react'; import '../../common/mock/match_media'; @@ -18,9 +17,15 @@ jest.mock('../../common/navigation/hooks'); describe('HeaderPage', () => { const mount = useMountAppended(); + let appMock: AppMockRenderer; + + beforeEach(() => { + jest.clearAllMocks(); + appMock = createAppMockRenderer(); + }); test('it renders', () => { - const wrapper = shallow( + const result = appMock.render( <TestProviders> <HeaderPage border subtitle="Test subtitle" subtitle2="Test subtitle 2" title="Test title"> <p>{'Test supplement'}</p> @@ -28,7 +33,10 @@ describe('HeaderPage', () => { </TestProviders> ); - expect(wrapper).toMatchSnapshot(); + expect(result.getByText('Test subtitle')).toBeInTheDocument(); + expect(result.getByText('Test subtitle 2')).toBeInTheDocument(); + expect(result.getByText('Test title')).toBeInTheDocument(); + expect(result.getByText('Test supplement')).toBeInTheDocument(); }); test('it renders the back link when provided', () => { @@ -140,12 +148,6 @@ describe('HeaderPage', () => { }); describe('Badges', () => { - let appMock: AppMockRenderer; - - beforeEach(() => { - appMock = createAppMockRenderer(); - }); - it('does not render the badge if the release is ga', () => { const renderResult = appMock.render(<HeaderPage title="Test title" />); diff --git a/x-pack/plugins/cases/public/components/tag_list/tags.tsx b/x-pack/plugins/cases/public/components/tags/tags.tsx similarity index 99% rename from x-pack/plugins/cases/public/components/tag_list/tags.tsx rename to x-pack/plugins/cases/public/components/tags/tags.tsx index ec8a84de1aa884..dd27a4a91ca12c 100644 --- a/x-pack/plugins/cases/public/components/tag_list/tags.tsx +++ b/x-pack/plugins/cases/public/components/tags/tags.tsx @@ -14,9 +14,11 @@ interface TagsProps { color?: string; gutterSize?: EuiBadgeGroupProps['gutterSize']; } + const MyEuiBadge = styled(EuiBadge)` max-width: 200px; `; + const TagsComponent: React.FC<TagsProps> = ({ tags, color = 'default', gutterSize }) => ( <> {tags.length > 0 && ( diff --git a/x-pack/plugins/cases/public/components/tag_list/translations.ts b/x-pack/plugins/cases/public/components/tags/translations.ts similarity index 100% rename from x-pack/plugins/cases/public/components/tag_list/translations.ts rename to x-pack/plugins/cases/public/components/tags/translations.ts diff --git a/x-pack/plugins/cases/public/components/types.ts b/x-pack/plugins/cases/public/components/types.ts index d31c297d18b1c1..d9ba8890aab314 100644 --- a/x-pack/plugins/cases/public/components/types.ts +++ b/x-pack/plugins/cases/public/components/types.ts @@ -5,6 +5,10 @@ * 2.0. */ +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; + export type { CaseActionConnector } from '../../common/ui/types'; export type ReleasePhase = 'experimental' | 'beta' | 'ga'; + +export type CurrentUserProfile = UserProfileWithAvatar | undefined; diff --git a/x-pack/plugins/cases/public/components/user_actions/assignees.test.tsx b/x-pack/plugins/cases/public/components/user_actions/assignees.test.tsx new file mode 100644 index 00000000000000..57cde43c9fee69 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_actions/assignees.test.tsx @@ -0,0 +1,230 @@ +/* + * 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 { EuiCommentList } from '@elastic/eui'; +import { render, screen } from '@testing-library/react'; + +import { Actions } from '../../../common/api'; +import { elasticUser, getUserAction } from '../../containers/mock'; +import { TestProviders } from '../../common/mock'; +import { createAssigneesUserActionBuilder, shouldAddAnd, shouldAddComma } from './assignees'; +import { getMockBuilderArgs } from './mock'; + +jest.mock('../../common/lib/kibana'); +jest.mock('../../common/navigation/hooks'); + +describe('createAssigneesUserActionBuilder', () => { + describe('shouldAddComma', () => { + it('returns false if there are only 2 items', () => { + expect(shouldAddComma(0, 2)).toBeFalsy(); + }); + + it('returns false it is the last items', () => { + expect(shouldAddComma(2, 3)).toBeFalsy(); + }); + }); + + describe('shouldAddAnd', () => { + it('returns false if there is only 1 item', () => { + expect(shouldAddAnd(0, 1)).toBeFalsy(); + }); + + it('returns false it is not the last items', () => { + expect(shouldAddAnd(1, 3)).toBeFalsy(); + }); + }); + + describe('component', () => { + const builderArgs = getMockBuilderArgs(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders assigned users', () => { + const userAction = getUserAction('assignees', Actions.add, { + createdBy: { + // damaged_raccoon uid + profileUid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0', + }, + }); + const builder = createAssigneesUserActionBuilder({ + ...builderArgs, + userAction, + }); + + const createdUserAction = builder.build(); + render( + <TestProviders> + <EuiCommentList comments={createdUserAction} /> + </TestProviders> + ); + + expect(screen.getByText('assigned')).toBeInTheDocument(); + expect(screen.getByText('themselves')).toBeInTheDocument(); + expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument(); + + expect(screen.getByTestId('ua-assignee-physical_dinosaur')).toContainElement( + screen.getByText('and') + ); + }); + + it('renders assigned users with a comma', () => { + const userAction = getUserAction('assignees', Actions.add, { + createdBy: { + // damaged_raccoon uid + profileUid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0', + }, + payload: { + assignees: [ + // These values map to uids in x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts + { uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }, + { uid: 'u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0' }, + { uid: 'u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0' }, + ], + }, + }); + const builder = createAssigneesUserActionBuilder({ + ...builderArgs, + userAction, + }); + + const createdUserAction = builder.build(); + render( + <TestProviders> + <EuiCommentList comments={createdUserAction} /> + </TestProviders> + ); + + expect(screen.getByText('assigned')).toBeInTheDocument(); + expect(screen.getByText('themselves,')).toBeInTheDocument(); + expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument(); + + expect(screen.getByTestId('ua-assignee-physical_dinosaur')).toContainElement( + screen.getByText(',') + ); + + expect(screen.getByText('Wet Dingo')).toBeInTheDocument(); + expect(screen.getByTestId('ua-assignee-wet_dingo')).toContainElement(screen.getByText('and')); + }); + + it('renders unassigned users', () => { + const userAction = getUserAction('assignees', Actions.delete, { + createdBy: { + // damaged_raccoon uid + profileUid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0', + }, + }); + const builder = createAssigneesUserActionBuilder({ + ...builderArgs, + userAction, + }); + + const createdUserAction = builder.build(); + render( + <TestProviders> + <EuiCommentList comments={createdUserAction} /> + </TestProviders> + ); + + expect(screen.getByText('unassigned')).toBeInTheDocument(); + expect(screen.getByText('themselves')).toBeInTheDocument(); + expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument(); + + expect(screen.getByTestId('ua-assignee-physical_dinosaur')).toContainElement( + screen.getByText('and') + ); + }); + + it('renders a single assigned user', () => { + const userAction = getUserAction('assignees', Actions.add, { + payload: { + assignees: [ + // only render the physical dinosaur + { uid: 'u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0' }, + ], + }, + }); + const builder = createAssigneesUserActionBuilder({ + ...builderArgs, + userAction, + }); + + const createdUserAction = builder.build(); + render( + <TestProviders> + <EuiCommentList comments={createdUserAction} /> + </TestProviders> + ); + + expect(screen.getByText('Physical Dinosaur')).toBeInTheDocument(); + expect(screen.queryByText('themselves,')).not.toBeInTheDocument(); + expect(screen.queryByText('and')).not.toBeInTheDocument(); + }); + + it('renders a single assigned user that is themselves using matching profile uids', () => { + const userAction = getUserAction('assignees', Actions.add, { + createdBy: { + ...elasticUser, + profileUid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0', + }, + payload: { + assignees: [ + // only render the damaged raccoon which is the current user + { uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }, + ], + }, + }); + const builder = createAssigneesUserActionBuilder({ + ...builderArgs, + userAction, + }); + + const createdUserAction = builder.build(); + render( + <TestProviders> + <EuiCommentList comments={createdUserAction} /> + </TestProviders> + ); + + expect(screen.getByText('themselves')).toBeInTheDocument(); + expect(screen.queryByText('Physical Dinosaur')).not.toBeInTheDocument(); + expect(screen.queryByText('and')).not.toBeInTheDocument(); + }); + + it('renders a single assigned user that is themselves using matching usernames', () => { + const userAction = getUserAction('assignees', Actions.add, { + createdBy: { + ...elasticUser, + username: 'damaged_raccoon', + }, + payload: { + assignees: [ + // only render the damaged raccoon which is the current user + { uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }, + ], + }, + }); + const builder = createAssigneesUserActionBuilder({ + ...builderArgs, + userAction, + }); + + const createdUserAction = builder.build(); + render( + <TestProviders> + <EuiCommentList comments={createdUserAction} /> + </TestProviders> + ); + + expect(screen.getByText('themselves')).toBeInTheDocument(); + expect(screen.queryByText('Physical Dinosaur')).not.toBeInTheDocument(); + expect(screen.queryByText('and')).not.toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_actions/assignees.tsx b/x-pack/plugins/cases/public/components/user_actions/assignees.tsx index 42580ede0b3f27..e0a499df056336 100644 --- a/x-pack/plugins/cases/public/components/user_actions/assignees.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/assignees.tsx @@ -5,13 +5,165 @@ * 2.0. */ -import type { UserActionBuilder } from './types'; +import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import React, { memo } from 'react'; +import { SnakeToCamelCase } from '../../../common/types'; +import { Actions, AssigneesUserAction, User } from '../../../common/api'; +import { getName } from '../user_profiles/display_name'; +import { Assignee } from '../user_profiles/types'; +import { UserToolTip } from '../user_profiles/user_tooltip'; +import { createCommonUpdateUserActionBuilder } from './common'; +import type { UserActionBuilder, UserActionResponse } from './types'; +import * as i18n from './translations'; +import { getUsernameDataTestSubj } from '../user_profiles/data_test_subject'; + +const FormatListItem: React.FC<{ + children: React.ReactElement; + index: number; + listSize: number; +}> = ({ children, index, listSize }) => { + if (shouldAddAnd(index, listSize)) { + return ( + <> + {i18n.AND} {children} + </> + ); + } else if (shouldAddComma(index, listSize)) { + return ( + <> + {children} + {','} + </> + ); + } + + return children; +}; +FormatListItem.displayName = 'FormatListItem'; + +export const shouldAddComma = (index: number, arrayLength: number) => { + return arrayLength > 2 && index !== arrayLength - 1; +}; + +export const shouldAddAnd = (index: number, arrayLength: number) => { + return arrayLength > 1 && index === arrayLength - 1; +}; + +const Themselves: React.FC<{ + index: number; + numOfAssigness: number; +}> = ({ index, numOfAssigness }) => ( + <FormatListItem index={index} listSize={numOfAssigness}> + <>{i18n.THEMSELVES}</> + </FormatListItem> +); +Themselves.displayName = 'Themselves'; + +const AssigneeComponent: React.FC<{ + assignee: Assignee; + index: number; + numOfAssigness: number; +}> = ({ assignee, index, numOfAssigness }) => ( + <FormatListItem index={index} listSize={numOfAssigness}> + <UserToolTip profile={assignee.profile}> + <strong>{getName(assignee.profile?.user)}</strong> + </UserToolTip> + </FormatListItem> +); +AssigneeComponent.displayName = 'Assignee'; + +interface AssigneesProps { + assignees: Assignee[]; + createdByUser: SnakeToCamelCase<User>; +} + +const AssigneesComponent = ({ assignees, createdByUser }: AssigneesProps) => ( + <> + {assignees.length > 0 && ( + <EuiFlexGroup alignItems="center" gutterSize="xs" wrap> + {assignees.map((assignee, index) => { + const usernameDataTestSubj = getUsernameDataTestSubj(assignee); + + return ( + <EuiFlexItem + data-test-subj={`ua-assignee-${usernameDataTestSubj}`} + grow={false} + key={assignee.uid} + > + <EuiText size="s" className="eui-textBreakWord"> + {doesAssigneeMatchCreatedByUser(assignee, createdByUser) ? ( + <Themselves index={index} numOfAssigness={assignees.length} /> + ) : ( + <AssigneeComponent + assignee={assignee} + index={index} + numOfAssigness={assignees.length} + /> + )} + </EuiText> + </EuiFlexItem> + ); + })} + </EuiFlexGroup> + )} + </> +); +AssigneesComponent.displayName = 'Assignees'; +const Assignees = memo(AssigneesComponent); + +const doesAssigneeMatchCreatedByUser = ( + assignee: Assignee, + createdByUser: SnakeToCamelCase<User> +) => { + return ( + assignee.uid === createdByUser?.profileUid || + // cases created before the assignees functionality will not have the profileUid so we'll need to fallback to the + // next best field + assignee?.profile?.user.username === createdByUser.username + ); +}; + +const getLabelTitle = ( + userAction: UserActionResponse<AssigneesUserAction>, + userProfiles?: Map<string, UserProfileWithAvatar> +) => { + const assignees = userAction.payload.assignees.map((assignee) => { + const profile = userProfiles?.get(assignee.uid); + return { + uid: assignee.uid, + profile, + }; + }); + + return ( + <EuiFlexGroup alignItems="baseline" gutterSize="xs" component="span" responsive={false}> + <EuiFlexItem data-test-subj="ua-assignees-label" grow={false}> + {userAction.action === Actions.add && i18n.ASSIGNED} + {userAction.action === Actions.delete && i18n.UNASSIGNED} + </EuiFlexItem> + <EuiFlexItem grow={false}> + <Assignees createdByUser={userAction.createdBy} assignees={assignees} /> + </EuiFlexItem> + </EuiFlexGroup> + ); +}; export const createAssigneesUserActionBuilder: UserActionBuilder = ({ userAction, handleOutlineComment, + userProfiles, }) => ({ build: () => { - return []; + const assigneesUserAction = userAction as UserActionResponse<AssigneesUserAction>; + const label = getLabelTitle(assigneesUserAction, userProfiles); + const commonBuilder = createCommonUpdateUserActionBuilder({ + userAction, + handleOutlineComment, + label, + icon: 'userAvatar', + }); + + return commonBuilder.build(); }, }); diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx index ef5b4418d454f7..d559a0981ad690 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx @@ -63,7 +63,12 @@ const getCreateCommentUserAction = ({ comment: Comment; } & Omit< UserActionBuilderArgs, - 'caseServices' | 'comments' | 'index' | 'handleOutlineComment' + | 'caseServices' + | 'comments' + | 'index' + | 'handleOutlineComment' + | 'userProfiles' + | 'currentUserProfile' >): EuiCommentProps[] => { switch (comment.type) { case CommentType.user: diff --git a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx index 60fc0e92d024bf..0991156cd3d4dc 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx @@ -32,6 +32,8 @@ const onShowAlertDetails = jest.fn(); const defaultProps = { caseServices: {}, caseUserActions: [], + userProfiles: new Map(), + currentUserProfile: undefined, connectors: [], actionsNavigation: { href: jest.fn(), onClick: jest.fn() }, getRuleDetailsHref: jest.fn(), @@ -440,6 +442,7 @@ describe(`UserActions`, () => { ).toBe('lock'); }); }); + it('shows a lockOpen icon if the action is unisolate/release', async () => { const isolateAction = [getHostIsolationUserAction()]; const props = { diff --git a/x-pack/plugins/cases/public/components/user_actions/index.tsx b/x-pack/plugins/cases/public/components/user_actions/index.tsx index 4a6bc85c7cbd70..1517450c4f62eb 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.tsx @@ -81,6 +81,8 @@ export const UserActions = React.memo( ({ caseServices, caseUserActions, + userProfiles, + currentUserProfile, data: caseData, getRuleDetailsHref, actionsNavigation, @@ -183,6 +185,8 @@ export const UserActions = React.memo( externalReferenceAttachmentTypeRegistry, persistableStateAttachmentTypeRegistry, userAction, + userProfiles, + currentUserProfile, caseServices, comments: caseData.comments, index, @@ -208,6 +212,8 @@ export const UserActions = React.memo( ), [ caseUserActions, + userProfiles, + currentUserProfile, externalReferenceAttachmentTypeRegistry, persistableStateAttachmentTypeRegistry, descriptionCommentListObj, diff --git a/x-pack/plugins/cases/public/components/user_actions/mock.ts b/x-pack/plugins/cases/public/components/user_actions/mock.ts index b3a7909b06929d..b963947a6282d5 100644 --- a/x-pack/plugins/cases/public/components/user_actions/mock.ts +++ b/x-pack/plugins/cases/public/components/user_actions/mock.ts @@ -10,6 +10,7 @@ import { SECURITY_SOLUTION_OWNER } from '../../../common/constants'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; import { basicCase, basicPush, getUserAction } from '../../containers/mock'; +import { userProfiles, userProfilesMap } from '../../containers/user_profiles/api.mock'; import { UserActionBuilderArgs } from './types'; export const getMockBuilderArgs = (): UserActionBuilderArgs => { @@ -63,6 +64,8 @@ export const getMockBuilderArgs = (): UserActionBuilderArgs => { return { userAction, + userProfiles: userProfilesMap, + currentUserProfile: userProfiles[0], externalReferenceAttachmentTypeRegistry, persistableStateAttachmentTypeRegistry, caseData: basicCase, diff --git a/x-pack/plugins/cases/public/components/user_actions/tags.tsx b/x-pack/plugins/cases/public/components/user_actions/tags.tsx index d5553a3f6f13d4..f9d0203a5647f4 100644 --- a/x-pack/plugins/cases/public/components/user_actions/tags.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/tags.tsx @@ -11,7 +11,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { Actions, TagsUserAction } from '../../../common/api'; import { UserActionBuilder, UserActionResponse } from './types'; import { createCommonUpdateUserActionBuilder } from './common'; -import { Tags } from '../tag_list/tags'; +import { Tags } from '../tags/tags'; import * as i18n from './translations'; const getLabelTitle = (userAction: UserActionResponse<TagsUserAction>) => { diff --git a/x-pack/plugins/cases/public/components/user_actions/translations.ts b/x-pack/plugins/cases/public/components/user_actions/translations.ts index b5b5d902d3a4de..91425c368286d9 100644 --- a/x-pack/plugins/cases/public/components/user_actions/translations.ts +++ b/x-pack/plugins/cases/public/components/user_actions/translations.ts @@ -78,3 +78,19 @@ export const CANCEL_BUTTON = i18n.translate('xpack.cases.caseView.delete.cancel' export const CONFIRM_BUTTON = i18n.translate('xpack.cases.caseView.delete.confirm', { defaultMessage: 'Delete', }); + +export const ASSIGNED = i18n.translate('xpack.cases.caseView.assigned', { + defaultMessage: 'assigned', +}); + +export const UNASSIGNED = i18n.translate('xpack.cases.caseView.unAssigned', { + defaultMessage: 'unassigned', +}); + +export const THEMSELVES = i18n.translate('xpack.cases.caseView.assignee.themselves', { + defaultMessage: 'themselves', +}); + +export const AND = i18n.translate('xpack.cases.caseView.assignee.and', { + defaultMessage: 'and', +}); diff --git a/x-pack/plugins/cases/public/components/user_actions/types.ts b/x-pack/plugins/cases/public/components/user_actions/types.ts index 8ba409468851ed..7477e6df8d5dce 100644 --- a/x-pack/plugins/cases/public/components/user_actions/types.ts +++ b/x-pack/plugins/cases/public/components/user_actions/types.ts @@ -6,6 +6,7 @@ */ import { EuiCommentProps } from '@elastic/eui'; +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; import { SnakeToCamelCase } from '../../../common/types'; import { ActionTypes, UserActionWithResponse } from '../../../common/api'; import { Case, CaseUserActions, Comment, UseFetchAlertData } from '../../containers/types'; @@ -17,10 +18,13 @@ import { UNSUPPORTED_ACTION_TYPES } from './constants'; import type { OnUpdateFields } from '../case_view/types'; import { ExternalReferenceAttachmentTypeRegistry } from '../../client/attachment_framework/external_reference_registry'; import { PersistableStateAttachmentTypeRegistry } from '../../client/attachment_framework/persistable_state_registry'; +import { CurrentUserProfile } from '../types'; export interface UserActionTreeProps { caseServices: CaseServices; caseUserActions: CaseUserActions[]; + userProfiles: Map<string, UserProfileWithAvatar>; + currentUserProfile: CurrentUserProfile; data: Case; getRuleDetailsHref?: RuleDetailsNavigation['href']; actionsNavigation?: ActionsNavigation; @@ -38,6 +42,8 @@ export type SupportedUserActionTypes = keyof Omit<typeof ActionTypes, Unsupporte export interface UserActionBuilderArgs { caseData: Case; + userProfiles: Map<string, UserProfileWithAvatar>; + currentUserProfile: CurrentUserProfile; externalReferenceAttachmentTypeRegistry: ExternalReferenceAttachmentTypeRegistry; persistableStateAttachmentTypeRegistry: PersistableStateAttachmentTypeRegistry; userAction: CaseUserActions; diff --git a/x-pack/plugins/cases/public/components/tag_list/schema.tsx b/x-pack/plugins/cases/public/components/user_profiles/data_test_subject.ts similarity index 61% rename from x-pack/plugins/cases/public/components/tag_list/schema.tsx rename to x-pack/plugins/cases/public/components/user_profiles/data_test_subject.ts index d7db17bd97cbde..23d952738aa4dc 100644 --- a/x-pack/plugins/cases/public/components/tag_list/schema.tsx +++ b/x-pack/plugins/cases/public/components/user_profiles/data_test_subject.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { FormSchema } from '../../common/shared_imports'; -import { schemaTags } from '../create/schema'; +import { Assignee } from './types'; -export const schema: FormSchema = { - tags: schemaTags, +export const getUsernameDataTestSubj = (assignee: Assignee) => { + return assignee.profile?.user.username ?? assignee.uid; }; diff --git a/x-pack/plugins/cases/public/components/user_profiles/display_name.test.ts b/x-pack/plugins/cases/public/components/user_profiles/display_name.test.ts new file mode 100644 index 00000000000000..fec173ac70c618 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/display_name.test.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 { getName } from './display_name'; + +describe('getName', () => { + it('returns unknown when the user is undefined', () => { + expect(getName()).toBe('Unknown'); + }); + + it('returns the full name', () => { + expect(getName({ full_name: 'name', username: 'username' })).toBe('name'); + }); + + it('returns the email if the full name is empty', () => { + expect(getName({ full_name: '', email: 'email', username: 'username' })).toBe('email'); + }); + + it('returns the email if the full name is undefined', () => { + expect(getName({ email: 'email', username: 'username' })).toBe('email'); + }); + + it('returns the username if the full name and email are empty', () => { + expect(getName({ full_name: '', email: '', username: 'username' })).toBe('username'); + }); + + it('returns the username if the full name and email are undefined', () => { + expect(getName({ username: 'username' })).toBe('username'); + }); + + it('returns the username is empty', () => { + expect(getName({ username: '' })).toBe('Unknown'); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/display_name.ts b/x-pack/plugins/cases/public/components/user_profiles/display_name.ts new file mode 100644 index 00000000000000..4abd9f276abaaf --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/display_name.ts @@ -0,0 +1,19 @@ +/* + * 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 { getUserDisplayName, UserProfileUserInfo } from '@kbn/user-profile-components'; +import { isEmpty } from 'lodash'; +import * as i18n from './translations'; + +export const getName = (user?: UserProfileUserInfo): string => { + if (!user) { + return i18n.UNKNOWN; + } + + const displayName = getUserDisplayName(user); + return !isEmpty(displayName) ? displayName : i18n.UNKNOWN; +}; diff --git a/x-pack/plugins/cases/public/components/user_profiles/empty_message.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/empty_message.test.tsx new file mode 100644 index 00000000000000..3c0c935d9316e8 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/empty_message.test.tsx @@ -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 React from 'react'; +import { EmptyMessage } from './empty_message'; +import { render } from '@testing-library/react'; + +describe('EmptyMessage', () => { + it('renders a null component', () => { + const { container } = render(<EmptyMessage />); + expect(container.firstChild).toBeNull(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_list/translations.ts b/x-pack/plugins/cases/public/components/user_profiles/empty_message.tsx similarity index 52% rename from x-pack/plugins/cases/public/components/user_list/translations.ts rename to x-pack/plugins/cases/public/components/user_profiles/empty_message.tsx index 73610e59593450..a2c713d5a9abce 100644 --- a/x-pack/plugins/cases/public/components/user_list/translations.ts +++ b/x-pack/plugins/cases/public/components/user_profiles/empty_message.tsx @@ -5,10 +5,9 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; +import React from 'react'; -export const SEND_EMAIL_ARIA = (user: string) => - i18n.translate('xpack.cases.caseView.sendEmalLinkAria', { - values: { user }, - defaultMessage: 'click to send an email to {user}', - }); +const EmptyMessageComponent: React.FC = () => null; +EmptyMessageComponent.displayName = 'EmptyMessage'; + +export const EmptyMessage = React.memo(EmptyMessageComponent); diff --git a/x-pack/plugins/cases/public/components/user_profiles/no_matches.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/no_matches.test.tsx new file mode 100644 index 00000000000000..3471aad3fec3c3 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/no_matches.test.tsx @@ -0,0 +1,18 @@ +/* + * 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 { NoMatches } from './no_matches'; +import { render, screen } from '@testing-library/react'; + +describe('NoMatches', () => { + it('renders the no matches messages', () => { + render(<NoMatches />); + + expect(screen.getByText('No matching users with required access.')); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/no_matches.tsx b/x-pack/plugins/cases/public/components/user_profiles/no_matches.tsx new file mode 100644 index 00000000000000..638d705fade867 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/no_matches.tsx @@ -0,0 +1,41 @@ +/* + * 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 { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, EuiText, EuiTextAlign } from '@elastic/eui'; +import React from 'react'; +import * as i18n from './translations'; + +const NoMatchesComponent: React.FC = () => { + return ( + <EuiFlexGroup + alignItems="center" + gutterSize="none" + direction="column" + justifyContent="spaceAround" + data-test-subj="case-user-profiles-assignees-popover-no-matches" + > + <EuiFlexItem grow={false}> + <EuiIcon type="userAvatar" size="xl" /> + <EuiSpacer size="xs" /> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <EuiTextAlign textAlign="center"> + <EuiText size="s" color="default"> + <strong>{i18n.NO_MATCHING_USERS}</strong> + <br /> + </EuiText> + <EuiText size="s" color="subdued"> + {i18n.TRY_MODIFYING_SEARCH} + </EuiText> + </EuiTextAlign> + </EuiFlexItem> + </EuiFlexGroup> + ); +}; +NoMatchesComponent.displayName = 'NoMatches'; + +export const NoMatches = React.memo(NoMatchesComponent); diff --git a/x-pack/plugins/cases/public/components/user_profiles/selected_status_message.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/selected_status_message.test.tsx new file mode 100644 index 00000000000000..b9611bb683d447 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/selected_status_message.test.tsx @@ -0,0 +1,24 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import { SelectedStatusMessage } from './selected_status_message'; + +describe('SelectedStatusMessage', () => { + it('does not render if the count is 0', () => { + const { container } = render(<SelectedStatusMessage selectedCount={0} message={'hello'} />); + + expect(container.firstChild).toBeNull(); + expect(screen.queryByText('hello')).not.toBeInTheDocument(); + }); + + it('renders the message when the count is great than 0', () => { + render(<SelectedStatusMessage selectedCount={1} message={'hello'} />); + + expect(screen.getByText('hello')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/selected_status_message.tsx b/x-pack/plugins/cases/public/components/user_profiles/selected_status_message.tsx new file mode 100644 index 00000000000000..87839fb7c34826 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/selected_status_message.tsx @@ -0,0 +1,22 @@ +/* + * 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'; + +const SelectedStatusMessageComponent: React.FC<{ + selectedCount: number; + message: string; +}> = ({ selectedCount, message }) => { + if (selectedCount <= 0) { + return null; + } + + return <>{message}</>; +}; +SelectedStatusMessageComponent.displayName = 'SelectedStatusMessage'; + +export const SelectedStatusMessage = React.memo(SelectedStatusMessageComponent); diff --git a/x-pack/plugins/cases/public/components/user_profiles/sort.test.ts b/x-pack/plugins/cases/public/components/user_profiles/sort.test.ts new file mode 100644 index 00000000000000..d2f64a05e7ce1c --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/sort.test.ts @@ -0,0 +1,118 @@ +/* + * 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 { userProfiles } from '../../containers/user_profiles/api.mock'; +import { bringCurrentUserToFrontAndSort, moveCurrentUserToBeginning } from './sort'; + +describe('sort', () => { + describe('moveCurrentUserToBeginning', () => { + it('returns an empty array if no profiles are provided', () => { + expect(moveCurrentUserToBeginning()).toBeUndefined(); + }); + + it("returns the profiles if the current profile isn't provided", () => { + const profiles = [{ uid: '1' }]; + expect(moveCurrentUserToBeginning(undefined, profiles)).toEqual(profiles); + }); + + it("returns the profiles if the current profile isn't found", () => { + const profiles = [{ uid: '1' }]; + expect(moveCurrentUserToBeginning({ uid: '2' }, profiles)).toEqual(profiles); + }); + + it('moves the current profile to the front', () => { + const profiles = [{ uid: '1' }, { uid: '2' }]; + expect(moveCurrentUserToBeginning({ uid: '2' }, profiles)).toEqual([ + { uid: '2' }, + { uid: '1' }, + ]); + }); + }); + + describe('bringCurrentUserToFrontAndSort', () => { + const unsortedProfiles = [...userProfiles].reverse(); + + it('returns a sorted list of users when the current user is undefined', () => { + expect(bringCurrentUserToFrontAndSort(undefined, unsortedProfiles)).toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + "user": Object { + "email": "physical_dinosaur@elastic.co", + "full_name": "Physical Dinosaur", + "username": "physical_dinosaur", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + ] + `); + }); + + it('returns a sorted list of users with the current user at the beginning', () => { + expect(bringCurrentUserToFrontAndSort(userProfiles[2], unsortedProfiles)) + .toMatchInlineSnapshot(` + Array [ + Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + Object { + "data": Object {}, + "enabled": true, + "uid": "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + "user": Object { + "email": "physical_dinosaur@elastic.co", + "full_name": "Physical Dinosaur", + "username": "physical_dinosaur", + }, + }, + ] + `); + }); + + it('returns undefined if profiles is undefined', () => { + expect(bringCurrentUserToFrontAndSort(userProfiles[2], undefined)).toBeUndefined(); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/sort.ts b/x-pack/plugins/cases/public/components/user_profiles/sort.ts new file mode 100644 index 00000000000000..e1e8018a21e356 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/sort.ts @@ -0,0 +1,53 @@ +/* + * 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 { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { sortBy } from 'lodash'; +import { CurrentUserProfile } from '../types'; + +export const getSortField = (profile: UserProfileWithAvatar) => + profile.user.full_name?.toLowerCase() ?? + profile.user.email?.toLowerCase() ?? + profile.user.username.toLowerCase(); + +export const moveCurrentUserToBeginning = <T extends { uid: string }>( + currentUserProfile?: T, + profiles?: T[] +) => { + if (!profiles) { + return; + } + + if (!currentUserProfile) { + return profiles; + } + + const currentProfileIndex = profiles.find((profile) => profile.uid === currentUserProfile.uid); + + if (!currentProfileIndex) { + return profiles; + } + + const profilesWithoutCurrentUser = profiles.filter( + (profile) => profile.uid !== currentUserProfile.uid + ); + + return [currentUserProfile, ...profilesWithoutCurrentUser]; +}; + +export const bringCurrentUserToFrontAndSort = ( + currentUserProfile: CurrentUserProfile, + profiles?: UserProfileWithAvatar[] +) => moveCurrentUserToBeginning(currentUserProfile, sortProfiles(profiles)); + +export const sortProfiles = (profiles?: UserProfileWithAvatar[]) => { + if (!profiles) { + return; + } + + return sortBy(profiles, getSortField); +}; diff --git a/x-pack/plugins/cases/public/components/user_profiles/translations.ts b/x-pack/plugins/cases/public/components/user_profiles/translations.ts new file mode 100644 index 00000000000000..beded4faf714b7 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/translations.ts @@ -0,0 +1,52 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export * from '../../common/translations'; + +export const REMOVE_ASSIGNEE = i18n.translate('xpack.cases.userProfile.removeAssigneeToolTip', { + defaultMessage: 'Remove assignee', +}); + +export const REMOVE_ASSIGNEE_ARIA_LABEL = i18n.translate( + 'xpack.cases.userProfile.removeAssigneeAriaLabel', + { + defaultMessage: 'click to remove assignee', + } +); + +export const MISSING_PROFILE = i18n.translate('xpack.cases.userProfile.missingProfile', { + defaultMessage: 'Unable to find user profile', +}); + +export const SEARCH_USERS = i18n.translate('xpack.cases.userProfile.selectableSearchPlaceholder', { + defaultMessage: 'Search users', +}); + +export const EDIT_ASSIGNEES = i18n.translate('xpack.cases.userProfile.editAssignees', { + defaultMessage: 'Edit assignees', +}); + +export const REMOVE_ASSIGNEES = i18n.translate( + 'xpack.cases.userProfile.suggestUsers.removeAssignees', + { + defaultMessage: 'Remove all assignees', + } +); + +export const ASSIGNEES = i18n.translate('xpack.cases.userProfile.assigneesTitle', { + defaultMessage: 'Assignees', +}); + +export const NO_MATCHING_USERS = i18n.translate('xpack.cases.userProfiles.noMatchingUsers', { + defaultMessage: 'No matching users with required access.', +}); + +export const TRY_MODIFYING_SEARCH = i18n.translate('xpack.cases.userProfiles.tryModifyingSearch', { + defaultMessage: 'Try modifying your search.', +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/types.ts b/x-pack/plugins/cases/public/components/user_profiles/types.ts new file mode 100644 index 00000000000000..f4acb29809d68b --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/types.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 { UserProfileWithAvatar } from '@kbn/user-profile-components'; + +export interface Assignee { + uid: string; + profile?: UserProfileWithAvatar; +} + +export interface AssigneeWithProfile extends Assignee { + profile: UserProfileWithAvatar; +} diff --git a/x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx b/x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx new file mode 100644 index 00000000000000..b98eef9efbd9f5 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/unknown_user.tsx @@ -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 React from 'react'; + +import { UserAvatar, UserAvatarProps } from '@kbn/user-profile-components'; + +interface CaseUnknownUserAvatarProps { + size: UserAvatarProps['size']; +} + +const CaseUnknownUserAvatarComponent: React.FC<CaseUnknownUserAvatarProps> = ({ size }) => { + return <UserAvatar data-test-subj="case-user-profile-avatar-unknown-user" size={size} />; +}; +CaseUnknownUserAvatarComponent.displayName = 'UnknownUserAvatar'; + +export const CaseUnknownUserAvatar = React.memo(CaseUnknownUserAvatarComponent); diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx new file mode 100644 index 00000000000000..1337239bf2dcc4 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.test.tsx @@ -0,0 +1,32 @@ +/* + * 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 { screen } from '@testing-library/react'; +import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import { userProfiles } from '../../containers/user_profiles/api.mock'; +import { CaseUserAvatar } from './user_avatar'; + +describe('CaseUserAvatar', () => { + let appMockRender: AppMockRenderer; + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + }); + + it('renders the avatar of Damaged Raccoon profile', () => { + appMockRender.render(<CaseUserAvatar size="s" profile={userProfiles[0]} />); + + expect(screen.getByText('DR')).toBeInTheDocument(); + }); + + it('renders the avatar of the unknown profile', () => { + appMockRender.render(<CaseUserAvatar size="s" />); + + expect(screen.getByText('?')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx new file mode 100644 index 00000000000000..be6a8ddfc9359f --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/user_avatar.tsx @@ -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 React from 'react'; + +import { UserAvatar, UserProfileWithAvatar, UserAvatarProps } from '@kbn/user-profile-components'; +import { CaseUnknownUserAvatar } from './unknown_user'; + +interface CaseUserAvatarProps { + size: UserAvatarProps['size']; + profile?: UserProfileWithAvatar; +} + +const CaseUserAvatarComponent: React.FC<CaseUserAvatarProps> = ({ size, profile }) => { + const dataTestSubjName = profile?.user.username; + + return profile !== undefined ? ( + <UserAvatar + user={profile.user} + avatar={profile.data.avatar} + data-test-subj={`case-user-profile-avatar-${dataTestSubjName}`} + size={size} + /> + ) : ( + <CaseUnknownUserAvatar size={size} /> + ); +}; + +CaseUserAvatarComponent.displayName = 'CaseUserAvatar'; + +export const CaseUserAvatar = React.memo(CaseUserAvatarComponent); diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_representation.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_representation.test.tsx new file mode 100644 index 00000000000000..5bda7ef8d3cbab --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/user_representation.test.tsx @@ -0,0 +1,86 @@ +/* + * 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 { fireEvent, screen } from '@testing-library/react'; +import { UserRepresentation, UserRepresentationProps } from './user_representation'; +import { userProfiles } from '../../containers/user_profiles/api.mock'; +import { + AppMockRenderer, + createAppMockRenderer, + noUpdateCasesPermissions, +} from '../../common/mock'; + +describe('UserRepresentation', () => { + const dataTestSubjGroup = `user-profile-assigned-user-group-${userProfiles[0].user.username}`; + const dataTestSubjCross = `user-profile-assigned-user-cross-${userProfiles[0].user.username}`; + const dataTestSubjGroupUnknown = `user-profile-assigned-user-group-unknownId`; + const dataTestSubjCrossUnknown = `user-profile-assigned-user-cross-unknownId`; + + let defaultProps: UserRepresentationProps; + let appMockRender: AppMockRenderer; + + beforeEach(() => { + defaultProps = { + assignee: { uid: userProfiles[0].uid, profile: userProfiles[0] }, + onRemoveAssignee: jest.fn(), + }; + + appMockRender = createAppMockRenderer(); + }); + + it('does not show the cross button when the user is not hovering over the row', () => { + appMockRender.render(<UserRepresentation {...defaultProps} />); + + expect(screen.queryByTestId(dataTestSubjCross)).toHaveStyle('opacity: 0'); + }); + + it('show the cross button when the user is hovering over the row', () => { + appMockRender.render(<UserRepresentation {...defaultProps} />); + + fireEvent.mouseEnter(screen.getByTestId(dataTestSubjGroup)); + + expect(screen.getByTestId(dataTestSubjCross)).toHaveStyle('opacity: 1'); + }); + + it('does not show the cross button when the user is hovering over the row and does not have update permissions', () => { + appMockRender = createAppMockRenderer({ permissions: noUpdateCasesPermissions() }); + appMockRender.render(<UserRepresentation {...defaultProps} />); + + fireEvent.mouseEnter(screen.getByTestId(dataTestSubjGroup)); + + expect(screen.queryByTestId(dataTestSubjCross)).not.toBeInTheDocument(); + }); + + it('show the cross button when hovering over the row of an unknown user', () => { + appMockRender.render( + <UserRepresentation {...{ ...defaultProps, assignee: { uid: 'unknownId' } }} /> + ); + + fireEvent.mouseEnter(screen.getByTestId(dataTestSubjGroupUnknown)); + + expect(screen.getByTestId(dataTestSubjCrossUnknown)).toHaveStyle('opacity: 1'); + }); + + it('shows and then removes the cross button when the user hovers and removes the mouse from over the row', () => { + appMockRender.render(<UserRepresentation {...defaultProps} />); + + fireEvent.mouseEnter(screen.getByTestId(dataTestSubjGroup)); + expect(screen.getByTestId(dataTestSubjCross)).toHaveStyle('opacity: 1'); + + fireEvent.mouseLeave(screen.getByTestId(dataTestSubjGroup)); + expect(screen.queryByTestId(dataTestSubjCross)).toHaveStyle('opacity: 0'); + }); + + it("renders unknown for the user's information", () => { + appMockRender.render( + <UserRepresentation {...{ ...defaultProps, assignee: { uid: 'unknownId' } }} /> + ); + + expect(screen.getByText('Unknown')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_representation.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_representation.tsx new file mode 100644 index 00000000000000..8ca7fdd435fc48 --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/user_representation.tsx @@ -0,0 +1,103 @@ +/* + * 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, { useCallback, useState } from 'react'; +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip } from '@elastic/eui'; +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { CaseUserAvatar } from './user_avatar'; +import { UserToolTip } from './user_tooltip'; +import { getName } from './display_name'; +import * as i18n from './translations'; +import { Assignee } from './types'; +import { useCasesContext } from '../cases_context/use_cases_context'; + +const UserAvatarWithName: React.FC<{ profile?: UserProfileWithAvatar }> = ({ profile }) => { + return ( + <EuiFlexGroup alignItems="center" gutterSize="s"> + <EuiFlexItem grow={false}> + <CaseUserAvatar size={'s'} profile={profile} /> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <EuiFlexGroup direction={'column'} gutterSize="none"> + <EuiFlexItem> + <EuiText size="s" className="eui-textBreakWord"> + {getName(profile?.user)} + </EuiText> + </EuiFlexItem> + </EuiFlexGroup> + </EuiFlexItem> + </EuiFlexGroup> + ); +}; +UserAvatarWithName.displayName = 'UserAvatarWithName'; + +export interface UserRepresentationProps { + assignee: Assignee; + onRemoveAssignee: (removedAssigneeUID: string) => void; +} + +const UserRepresentationComponent: React.FC<UserRepresentationProps> = ({ + assignee, + onRemoveAssignee, +}) => { + const { permissions } = useCasesContext(); + const [isHovering, setIsHovering] = useState(false); + + const removeAssigneeCallback = useCallback( + () => onRemoveAssignee(assignee.uid), + [onRemoveAssignee, assignee.uid] + ); + + const onFocus = useCallback(() => setIsHovering(true), []); + const onFocusLeave = useCallback(() => setIsHovering(false), []); + + const usernameDataTestSubj = assignee.profile?.user.username ?? assignee.uid; + + return ( + <EuiFlexGroup + onMouseEnter={onFocus} + onMouseLeave={onFocusLeave} + alignItems="center" + gutterSize="s" + justifyContent="spaceBetween" + data-test-subj={`user-profile-assigned-user-group-${usernameDataTestSubj}`} + > + <EuiFlexItem grow={false}> + <UserToolTip profile={assignee.profile}> + <UserAvatarWithName profile={assignee.profile} /> + </UserToolTip> + </EuiFlexItem> + {permissions.update && ( + <EuiFlexItem grow={false}> + <EuiToolTip + position="left" + content={i18n.REMOVE_ASSIGNEE} + data-test-subj={`user-profile-assigned-user-cross-tooltip-${usernameDataTestSubj}`} + > + <EuiButtonIcon + css={{ + opacity: isHovering ? 1 : 0, + }} + onFocus={onFocus} + onBlur={onFocusLeave} + data-test-subj={`user-profile-assigned-user-cross-${usernameDataTestSubj}`} + aria-label={i18n.REMOVE_ASSIGNEE_ARIA_LABEL} + iconType="cross" + color="danger" + iconSize="m" + onClick={removeAssigneeCallback} + /> + </EuiToolTip> + </EuiFlexItem> + )} + </EuiFlexGroup> + ); +}; + +UserRepresentationComponent.displayName = 'UserRepresentation'; + +export const UserRepresentation = React.memo(UserRepresentationComponent); diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx new file mode 100644 index 00000000000000..17d26a39c48f6d --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.test.tsx @@ -0,0 +1,174 @@ +/* + * 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 { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import React from 'react'; +import { UserToolTip } from './user_tooltip'; + +describe('UserToolTip', () => { + it('renders the tooltip when hovering', async () => { + const profile: UserProfileWithAvatar = { + uid: '1', + enabled: true, + data: { + avatar: { + initials: 'SU', + }, + }, + user: { + username: 'user', + email: 'some.user@google.com', + full_name: 'Some Super User', + }, + }; + + render( + <UserToolTip profile={profile}> + <strong>{'case user'}</strong> + </UserToolTip> + ); + + fireEvent.mouseOver(screen.getByText('case user')); + + await waitFor(() => screen.getByTestId('user-profile-tooltip')); + expect(screen.getByText('Some Super User')).toBeInTheDocument(); + expect(screen.getByText('some.user@google.com')).toBeInTheDocument(); + expect(screen.getByText('SU')).toBeInTheDocument(); + }); + + it('only shows the display name if full name is missing', async () => { + const profile: UserProfileWithAvatar = { + uid: '1', + enabled: true, + data: { + avatar: { + initials: 'SU', + }, + }, + user: { + username: 'user', + email: 'some.user@google.com', + }, + }; + + render( + <UserToolTip profile={profile}> + <strong>{'case user'}</strong> + </UserToolTip> + ); + + fireEvent.mouseOver(screen.getByText('case user')); + + await waitFor(() => screen.getByTestId('user-profile-tooltip')); + expect(screen.queryByText('Some Super User')).not.toBeInTheDocument(); + expect(screen.getByText('some.user@google.com')).toBeInTheDocument(); + expect(screen.getByText('SU')).toBeInTheDocument(); + }); + + it('only shows the full name if display name is missing', async () => { + const profile: UserProfileWithAvatar = { + uid: '1', + enabled: true, + data: { + avatar: { + initials: 'SU', + }, + }, + user: { + username: 'user', + full_name: 'Some Super User', + email: 'some.user@google.com', + }, + }; + + render( + <UserToolTip profile={profile}> + <strong>{'case user'}</strong> + </UserToolTip> + ); + + fireEvent.mouseOver(screen.getByText('case user')); + + await waitFor(() => screen.getByTestId('user-profile-tooltip')); + expect(screen.getByText('Some Super User')).toBeInTheDocument(); + expect(screen.getByText('some.user@google.com')).toBeInTheDocument(); + expect(screen.getByText('SU')).toBeInTheDocument(); + }); + + it('only shows the email once when display name and full name are not defined', async () => { + const profile: UserProfileWithAvatar = { + uid: '1', + enabled: true, + data: { + avatar: { + initials: 'SU', + }, + }, + user: { + username: 'user', + email: 'some.user@google.com', + }, + }; + + render( + <UserToolTip profile={profile}> + <strong>{'case user'}</strong> + </UserToolTip> + ); + + fireEvent.mouseOver(screen.getByText('case user')); + + await waitFor(() => screen.getByTestId('user-profile-tooltip')); + expect(screen.queryByText('Some Super User')).not.toBeInTheDocument(); + expect(screen.getByText('some.user@google.com')).toBeInTheDocument(); + expect(screen.getByText('SU')).toBeInTheDocument(); + }); + + it('only shows the username once when all other fields are undefined', async () => { + const profile: UserProfileWithAvatar = { + uid: '1', + enabled: true, + data: { + avatar: { + initials: 'SU', + }, + }, + user: { + username: 'user', + }, + }; + + render( + <UserToolTip profile={profile}> + <strong>{'case user'}</strong> + </UserToolTip> + ); + + fireEvent.mouseOver(screen.getByText('case user')); + + await waitFor(() => screen.getByTestId('user-profile-tooltip')); + expect(screen.queryByText('Some Super User')).not.toBeInTheDocument(); + expect(screen.queryByText('some.user@google.com')).not.toBeInTheDocument(); + expect(screen.getByText('user')).toBeInTheDocument(); + expect(screen.getByText('SU')).toBeInTheDocument(); + }); + + it('shows an unknown users display name and avatar', async () => { + render( + <UserToolTip> + <strong>{'case user'}</strong> + </UserToolTip> + ); + + fireEvent.mouseOver(screen.getByText('case user')); + + await waitFor(() => screen.getByTestId('user-profile-tooltip')); + expect(screen.getByText('Unable to find user profile')).toBeInTheDocument(); + expect(screen.getByText('?')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx new file mode 100644 index 00000000000000..9c837997b9a1fb --- /dev/null +++ b/x-pack/plugins/cases/public/components/user_profiles/user_tooltip.tsx @@ -0,0 +1,105 @@ +/* + * 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 { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip } from '@elastic/eui'; +import { UserProfileUserInfo, UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { CaseUserAvatar } from './user_avatar'; +import { getName } from './display_name'; +import * as i18n from './translations'; + +const UserFullInformation: React.FC<{ profile?: UserProfileWithAvatar }> = React.memo( + ({ profile }) => { + if (profile?.user.full_name) { + return ( + <EuiText size="s" className="eui-textBreakWord"> + <strong data-test-subj="user-profile-tooltip-full-name">{profile.user.full_name}</strong> + </EuiText> + ); + } + + return ( + <EuiText + size="s" + className="eui-textBreakWord" + data-test-subj="user-profile-tooltip-single-name" + > + <strong>{getNameOrMissingText(profile?.user)}</strong> + </EuiText> + ); + } +); + +const getNameOrMissingText = (user?: UserProfileUserInfo) => { + if (!user) { + return i18n.MISSING_PROFILE; + } + + return getName(user); +}; + +UserFullInformation.displayName = 'UserFullInformation'; + +interface UserFullRepresentationProps { + profile?: UserProfileWithAvatar; +} + +const UserFullRepresentationComponent: React.FC<UserFullRepresentationProps> = ({ profile }) => { + return ( + <EuiFlexGroup alignItems="center" gutterSize="s"> + <EuiFlexItem grow={false} data-test-subj="user-profile-tooltip-avatar"> + <CaseUserAvatar size={'m'} profile={profile} /> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <EuiFlexGroup direction={'column'} gutterSize="none"> + <EuiFlexItem> + <UserFullInformation profile={profile} /> + </EuiFlexItem> + {profile && displayEmail(profile) && ( + <EuiFlexItem grow={false}> + <EuiText + size="s" + className="eui-textBreakWord" + data-test-subj="user-profile-tooltip-email" + > + {profile.user.email} + </EuiText> + </EuiFlexItem> + )} + </EuiFlexGroup> + </EuiFlexItem> + </EuiFlexGroup> + ); +}; + +UserFullRepresentationComponent.displayName = 'UserFullRepresentation'; + +const displayEmail = (profile?: UserProfileWithAvatar) => { + return profile?.user.full_name && profile?.user.email; +}; + +export interface UserToolTipProps { + children: React.ReactElement; + profile?: UserProfileWithAvatar; +} + +const UserToolTipComponent: React.FC<UserToolTipProps> = ({ children, profile }) => { + return ( + <EuiToolTip + display="inlineBlock" + position="top" + content={<UserFullRepresentationComponent profile={profile} />} + data-test-subj="user-profile-tooltip" + > + {children} + </EuiToolTip> + ); +}; + +UserToolTipComponent.displayName = 'UserToolTip'; +export const UserToolTip = React.memo(UserToolTipComponent); diff --git a/x-pack/plugins/cases/public/containers/__mocks__/api.ts b/x-pack/plugins/cases/public/containers/__mocks__/api.ts index f781daac156976..2b431351230808 100644 --- a/x-pack/plugins/cases/public/containers/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/containers/__mocks__/api.ts @@ -26,7 +26,6 @@ import { casesStatus, caseUserActions, pushedCase, - respReporters, tags, } from '../mock'; import { ResolvedCase, SeverityAll } from '../../../common/ui/types'; @@ -34,11 +33,12 @@ import { CasePatchRequest, CasePostRequest, CommentRequest, - User, CaseStatuses, SingleCaseMetricsResponse, } from '../../../common/api'; import type { ValidFeatureId } from '@kbn/rule-data-utils'; +import { UserProfile } from '@kbn/security-plugin/common'; +import { userProfiles } from '../user_profiles/api.mock'; export const getCase = async ( caseId: string, @@ -62,8 +62,7 @@ export const getCasesStatus = async (signal: AbortSignal): Promise<CasesStatus> export const getTags = async (signal: AbortSignal): Promise<string[]> => Promise.resolve(tags); -export const getReporters = async (signal: AbortSignal): Promise<User[]> => - Promise.resolve(respReporters); +export const findAssignees = async (): Promise<UserProfile[]> => userProfiles; export const getCaseUserActions = async ( caseId: string, @@ -75,6 +74,7 @@ export const getCases = async ({ severity: SeverityAll, search: '', searchFields: [], + assignees: [], reporters: [], status: CaseStatuses.open, tags: [], diff --git a/x-pack/plugins/cases/public/containers/api.test.tsx b/x-pack/plugins/cases/public/containers/api.test.tsx index 45cde4c4f94cba..e51224dc593dcb 100644 --- a/x-pack/plugins/cases/public/containers/api.test.tsx +++ b/x-pack/plugins/cases/public/containers/api.test.tsx @@ -23,7 +23,6 @@ import { getCase, getCases, getCaseUserActions, - getReporters, getTags, patchCase, patchCasesStatus, @@ -48,8 +47,6 @@ import { cases, caseUserActions, pushedCase, - reporters, - respReporters, tags, caseUserActionsSnake, casesStatusSnake, @@ -200,6 +197,7 @@ describe('Cases API', () => { query: { ...DEFAULT_QUERY_PARAMS, searchFields: DEFAULT_FILTER_OPTIONS.searchFields, + assignees: [], reporters: [], tags: [], owner: [SECURITY_SOLUTION_OWNER], @@ -212,7 +210,8 @@ describe('Cases API', () => { await getCases({ filterOptions: { ...DEFAULT_FILTER_OPTIONS, - reporters: [...respReporters, { username: null, full_name: null, email: null }], + assignees: ['123'], + reporters: [{ username: 'username', full_name: null, email: null }], tags, status: CaseStatuses.open, search: 'hello', @@ -225,7 +224,8 @@ describe('Cases API', () => { method: 'GET', query: { ...DEFAULT_QUERY_PARAMS, - reporters, + assignees: ['123'], + reporters: ['username'], tags: ['coke', 'pepsi'], search: 'hello', searchFields: DEFAULT_FILTER_OPTIONS.searchFields, @@ -250,6 +250,7 @@ describe('Cases API', () => { query: { ...DEFAULT_QUERY_PARAMS, searchFields: DEFAULT_FILTER_OPTIONS.searchFields, + assignees: [], reporters: [], tags: [], severity: CaseSeverity.HIGH, @@ -272,6 +273,7 @@ describe('Cases API', () => { query: { ...DEFAULT_QUERY_PARAMS, searchFields: DEFAULT_FILTER_OPTIONS.searchFields, + assignees: [], reporters: [], tags: [], }, @@ -285,7 +287,8 @@ describe('Cases API', () => { await getCases({ filterOptions: { ...DEFAULT_FILTER_OPTIONS, - reporters: [...respReporters, { username: null, full_name: null, email: null }], + assignees: ['123'], + reporters: [{ username: undefined, full_name: undefined, email: undefined }], tags: weirdTags, status: CaseStatuses.open, search: 'hello', @@ -298,7 +301,8 @@ describe('Cases API', () => { method: 'GET', query: { ...DEFAULT_QUERY_PARAMS, - reporters, + assignees: ['123'], + reporters: [], tags: ['(', '"double"'], search: 'hello', searchFields: DEFAULT_FILTER_OPTIONS.searchFields, @@ -378,29 +382,6 @@ describe('Cases API', () => { }); }); - describe('getReporters', () => { - beforeEach(() => { - fetchMock.mockClear(); - fetchMock.mockResolvedValue(respReporters); - }); - - test('should be called with correct check url, method, signal', async () => { - await getReporters(abortCtrl.signal, [SECURITY_SOLUTION_OWNER]); - expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/reporters`, { - method: 'GET', - signal: abortCtrl.signal, - query: { - owner: [SECURITY_SOLUTION_OWNER], - }, - }); - }); - - test('should return correct response', async () => { - const resp = await getReporters(abortCtrl.signal, [SECURITY_SOLUTION_OWNER]); - expect(resp).toEqual(respReporters); - }); - }); - describe('getTags', () => { beforeEach(() => { fetchMock.mockClear(); diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts index 70b9c4033a424c..2b7e8910fb9daf 100644 --- a/x-pack/plugins/cases/public/containers/api.ts +++ b/x-pack/plugins/cases/public/containers/api.ts @@ -164,6 +164,7 @@ export const getCases = async ({ search: '', searchFields: [], severity: SeverityAll, + assignees: [], reporters: [], status: StatusAll, tags: [], @@ -180,6 +181,7 @@ export const getCases = async ({ const query = { ...(filterOptions.status !== StatusAll ? { status: filterOptions.status } : {}), ...(filterOptions.severity !== SeverityAll ? { severity: filterOptions.severity } : {}), + assignees: filterOptions.assignees, reporters: filterOptions.reporters.map((r) => r.username ?? '').filter((r) => r !== ''), tags: filterOptions.tags, ...(filterOptions.search.length > 0 ? { search: filterOptions.search } : {}), diff --git a/x-pack/plugins/cases/public/containers/constants.ts b/x-pack/plugins/cases/public/containers/constants.ts index 3a04b411cb8e74..a87d7733034474 100644 --- a/x-pack/plugins/cases/public/containers/constants.ts +++ b/x-pack/plugins/cases/public/containers/constants.ts @@ -24,3 +24,4 @@ export const CASE_TAGS_CACHE_KEY = 'case-tags'; export const USER_PROFILES_CACHE_KEY = 'user-profiles'; export const USER_PROFILES_SUGGEST_CACHE_KEY = 'suggest'; export const USER_PROFILES_BULK_GET_CACHE_KEY = 'bulk-get'; +export const USER_PROFILES_GET_CURRENT_CACHE_KEY = 'get-current'; diff --git a/x-pack/plugins/cases/public/containers/mock.ts b/x-pack/plugins/cases/public/containers/mock.ts index 92e601dd0c9e9c..812349e96fce73 100644 --- a/x-pack/plugins/cases/public/containers/mock.ts +++ b/x-pack/plugins/cases/public/containers/mock.ts @@ -228,7 +228,8 @@ export const basicCase: Case = { settings: { syncAlerts: true, }, - assignees: [], + // damaged_raccoon uid + assignees: [{ uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }], }; export const caseWithAlerts = { @@ -553,13 +554,6 @@ export const pushedCaseSnake = { external_service: { ...basicPushSnake, connector_id: pushConnectorId }, }; -export const reporters: string[] = ['alexis', 'kim', 'maria', 'steph']; -export const respReporters = [ - { username: 'alexis', full_name: null, email: null }, - { username: 'kim', full_name: null, email: null }, - { username: 'maria', full_name: null, email: null }, - { username: 'steph', full_name: null, email: null }, -]; export const casesSnake: CasesResponse = [ basicCaseSnake, { ...pushedCaseSnake, id: '1', totalComment: 0, comments: [] }, @@ -688,6 +682,19 @@ export const getUserAction = ( payload: { title: 'a title' }, ...overrides, }; + case ActionTypes.assignees: + return { + ...commonProperties, + type: ActionTypes.assignees, + payload: { + assignees: [ + // These values map to uids in x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts + { uid: 'u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0' }, + { uid: 'u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0' }, + ], + }, + ...overrides, + }; default: return { diff --git a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx index c5dbf017da8c94..a9d80181b58f75 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.test.tsx @@ -62,6 +62,7 @@ describe('useGetCaseUserActions', () => { caseServices: {}, hasDataToPush: true, participants: [elasticUser], + profileUids: new Set(), }, isError: false, isLoading: false, @@ -87,6 +88,84 @@ describe('useGetCaseUserActions', () => { expect(addError).toHaveBeenCalled(); }); + describe('getProfileUids', () => { + it('aggregates the uids from an assignment add user action', async () => { + jest + .spyOn(api, 'getCaseUserActions') + .mockReturnValue( + Promise.resolve([...caseUserActions, getUserAction('assignees', Actions.add)]) + ); + + await act(async () => { + const { result } = renderHook<string, UseGetCaseUserActions>( + () => useGetCaseUserActions(basicCase.id, basicCase.connector.id), + { wrapper } + ); + + await waitFor(() => { + expect(result.current.data?.profileUids).toMatchInlineSnapshot(` + Set { + "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + } + `); + }); + }); + }); + + it('ignores duplicate uids', async () => { + jest + .spyOn(api, 'getCaseUserActions') + .mockReturnValue( + Promise.resolve([ + ...caseUserActions, + getUserAction('assignees', Actions.add), + getUserAction('assignees', Actions.add), + ]) + ); + + await act(async () => { + const { result } = renderHook<string, UseGetCaseUserActions>( + () => useGetCaseUserActions(basicCase.id, basicCase.connector.id), + { wrapper } + ); + + await waitFor(() => { + expect(result.current.data?.profileUids).toMatchInlineSnapshot(` + Set { + "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + } + `); + }); + }); + }); + + it('aggregates the uids from an assignment delete user action', async () => { + jest + .spyOn(api, 'getCaseUserActions') + .mockReturnValue( + Promise.resolve([...caseUserActions, getUserAction('assignees', Actions.delete)]) + ); + + await act(async () => { + const { result } = renderHook<string, UseGetCaseUserActions>( + () => useGetCaseUserActions(basicCase.id, basicCase.connector.id), + { wrapper } + ); + + await waitFor(() => { + expect(result.current.data?.profileUids).toMatchInlineSnapshot(` + Set { + "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + } + `); + }); + }); + }); + }); + describe('getPushedInfo', () => { it('Correctly marks first/last index - hasDataToPush: false', () => { const userActions = [...caseUserActions, getUserAction('pushed', Actions.push_to_service)]; diff --git a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx index da695201d6d768..1d36521d0b6f41 100644 --- a/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_case_user_actions.tsx @@ -208,6 +208,21 @@ export const getPushedInfo = ( }; }; +export const getProfileUids = (userActions: CaseUserActions[]) => { + const uids = userActions.reduce<Set<string>>((acc, userAction) => { + if (userAction.type === ActionTypes.assignees) { + const uidsFromPayload = userAction.payload.assignees.map((assignee) => assignee.uid); + for (const uid of uidsFromPayload) { + acc.add(uid); + } + } + + return acc; + }, new Set()); + + return uids; +}; + export const useGetCaseUserActions = (caseId: string, caseConnectorId: string) => { const toasts = useToasts(); const abortCtrlRef = new AbortController(); @@ -221,9 +236,12 @@ export const useGetCaseUserActions = (caseId: string, caseConnectorId: string) = const caseUserActions = !isEmpty(response) ? response : []; const pushedInfo = getPushedInfo(caseUserActions, caseConnectorId); + const profileUids = getProfileUids(caseUserActions); + return { caseUserActions, participants, + profileUids, ...pushedInfo, }; }, diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.tsx index ce19e68fa17988..7b046cac3f13fe 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases.tsx @@ -19,6 +19,7 @@ export const DEFAULT_FILTER_OPTIONS: FilterOptions = { search: '', searchFields: DEFAULT_SEARCH_FIELDS, severity: SeverityAll, + assignees: [], reporters: [], status: StatusAll, tags: [], diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx index 6601a104d9f7d0..a8747a2bd43a55 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_metrics.test.tsx @@ -15,7 +15,7 @@ import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; jest.mock('../api'); jest.mock('../common/lib/kibana'); -describe('useGetReporters', () => { +describe('useGetCasesMetrics', () => { beforeEach(() => { jest.clearAllMocks(); jest.restoreAllMocks(); diff --git a/x-pack/plugins/cases/public/containers/use_get_reporters.test.tsx b/x-pack/plugins/cases/public/containers/use_get_reporters.test.tsx deleted file mode 100644 index 38d47d3aa9cbbc..00000000000000 --- a/x-pack/plugins/cases/public/containers/use_get_reporters.test.tsx +++ /dev/null @@ -1,111 +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 React from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; -import { useGetReporters, UseGetReporters } from './use_get_reporters'; -import { reporters, respReporters } from './mock'; -import * as api from './api'; -import { TestProviders } from '../common/mock'; -import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; - -jest.mock('./api'); -jest.mock('../common/lib/kibana'); - -describe('useGetReporters', () => { - const abortCtrl = new AbortController(); - beforeEach(() => { - jest.clearAllMocks(); - jest.restoreAllMocks(); - }); - - it('init', async () => { - const { result } = renderHook<string, UseGetReporters>(() => useGetReporters(), { - wrapper: ({ children }) => <TestProviders>{children}</TestProviders>, - }); - - await act(async () => { - expect(result.current).toEqual({ - reporters: [], - respReporters: [], - isLoading: true, - isError: false, - fetchReporters: result.current.fetchReporters, - }); - }); - }); - - it('calls getReporters api', async () => { - const spyOnGetReporters = jest.spyOn(api, 'getReporters'); - await act(async () => { - const { waitForNextUpdate } = renderHook<string, UseGetReporters>(() => useGetReporters(), { - wrapper: ({ children }) => <TestProviders>{children}</TestProviders>, - }); - await waitForNextUpdate(); - expect(spyOnGetReporters).toBeCalledWith(abortCtrl.signal, [SECURITY_SOLUTION_OWNER]); - }); - }); - - it('fetch reporters', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook<string, UseGetReporters>( - () => useGetReporters(), - { - wrapper: ({ children }) => <TestProviders>{children}</TestProviders>, - } - ); - await waitForNextUpdate(); - expect(result.current).toEqual({ - reporters, - respReporters, - isLoading: false, - isError: false, - fetchReporters: result.current.fetchReporters, - }); - }); - }); - - it('refetch reporters', async () => { - const spyOnGetReporters = jest.spyOn(api, 'getReporters'); - await act(async () => { - const { result, waitForNextUpdate } = renderHook<string, UseGetReporters>( - () => useGetReporters(), - { - wrapper: ({ children }) => <TestProviders>{children}</TestProviders>, - } - ); - await waitForNextUpdate(); - result.current.fetchReporters(); - expect(spyOnGetReporters).toHaveBeenCalledTimes(2); - }); - }); - - it('unhappy path', async () => { - const spyOnGetReporters = jest.spyOn(api, 'getReporters'); - spyOnGetReporters.mockImplementation(() => { - throw new Error('Something went wrong'); - }); - - await act(async () => { - const { result, waitForNextUpdate } = renderHook<string, UseGetReporters>( - () => useGetReporters(), - { - wrapper: ({ children }) => <TestProviders>{children}</TestProviders>, - } - ); - await waitForNextUpdate(); - - expect(result.current).toEqual({ - reporters: [], - respReporters: [], - isLoading: false, - isError: true, - fetchReporters: result.current.fetchReporters, - }); - }); - }); -}); diff --git a/x-pack/plugins/cases/public/containers/use_get_reporters.tsx b/x-pack/plugins/cases/public/containers/use_get_reporters.tsx deleted file mode 100644 index ce8aa4b961c230..00000000000000 --- a/x-pack/plugins/cases/public/containers/use_get_reporters.tsx +++ /dev/null @@ -1,95 +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 { useCallback, useEffect, useState, useRef } from 'react'; -import { isEmpty } from 'lodash/fp'; - -import { User } from '../../common/api'; -import { getReporters } from './api'; -import * as i18n from './translations'; -import { useToasts } from '../common/lib/kibana'; -import { useCasesContext } from '../components/cases_context/use_cases_context'; - -interface ReportersState { - reporters: string[]; - respReporters: User[]; - isLoading: boolean; - isError: boolean; -} - -const initialData: ReportersState = { - reporters: [], - respReporters: [], - isLoading: true, - isError: false, -}; - -export interface UseGetReporters extends ReportersState { - fetchReporters: () => void; -} - -export const useGetReporters = (): UseGetReporters => { - const { owner } = useCasesContext(); - const [reportersState, setReporterState] = useState<ReportersState>(initialData); - - const toasts = useToasts(); - const isCancelledRef = useRef(false); - const abortCtrlRef = useRef(new AbortController()); - - const fetchReporters = useCallback(async () => { - try { - isCancelledRef.current = false; - abortCtrlRef.current.abort(); - abortCtrlRef.current = new AbortController(); - setReporterState({ - ...reportersState, - isLoading: true, - }); - - const response = await getReporters(abortCtrlRef.current.signal, owner); - const myReporters = response - .map((r) => (r.full_name == null || isEmpty(r.full_name) ? r.username ?? '' : r.full_name)) - .filter((u) => !isEmpty(u)); - - if (!isCancelledRef.current) { - setReporterState({ - reporters: myReporters, - respReporters: response, - isLoading: false, - isError: false, - }); - } - } catch (error) { - if (!isCancelledRef.current) { - if (error.name !== 'AbortError') { - toasts.addError( - error.body && error.body.message ? new Error(error.body.message) : error, - { title: i18n.ERROR_TITLE } - ); - } - - setReporterState({ - reporters: [], - respReporters: [], - isLoading: false, - isError: true, - }); - } - } - }, [owner, reportersState, toasts]); - - useEffect(() => { - fetchReporters(); - return () => { - isCancelledRef.current = true; - abortCtrlRef.current.abort(); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return { ...reportersState, fetchReporters }; -}; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts b/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts index 36c88451124ca1..6901852a405fa2 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/__mocks__/api.ts @@ -8,8 +8,8 @@ import { UserProfile } from '@kbn/security-plugin/common'; import { userProfiles } from '../api.mock'; -export const suggestUserProfiles = async (): Promise<UserProfile[]> => - Promise.resolve(userProfiles); +export const suggestUserProfiles = async (): Promise<UserProfile[]> => userProfiles; -export const bulkGetUserProfiles = async (): Promise<UserProfile[]> => - Promise.resolve(userProfiles); +export const bulkGetUserProfiles = async (): Promise<UserProfile[]> => userProfiles; + +export const getCurrentUserProfile = async (): Promise<UserProfile> => userProfiles[0]; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts b/x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts index e9382f7092ae01..1296cf98788274 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/api.mock.ts @@ -41,3 +41,5 @@ export const userProfiles: UserProfile[] = [ ]; export const userProfilesIds = userProfiles.map((profile) => profile.uid); + +export const userProfilesMap = new Map(userProfiles.map((profile) => [profile.uid, profile])); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/api.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/api.test.ts index 7234cc9fb54fe7..0f7c9d9c31fa96 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/api.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/api.test.ts @@ -5,9 +5,11 @@ * 2.0. */ +import { securityMock } from '@kbn/security-plugin/public/mocks'; +import { SecurityPluginStart } from '@kbn/security-plugin/public'; import { GENERAL_CASES_OWNER } from '../../../common/constants'; import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; -import { bulkGetUserProfiles, suggestUserProfiles } from './api'; +import { bulkGetUserProfiles, getCurrentUserProfile, suggestUserProfiles } from './api'; import { userProfiles, userProfilesIds } from './api.mock'; describe('User profiles API', () => { @@ -24,7 +26,7 @@ describe('User profiles API', () => { const res = await suggestUserProfiles({ http, name: 'elastic', - owner: [GENERAL_CASES_OWNER], + owners: [GENERAL_CASES_OWNER], signal: abortCtrl.signal, }); @@ -35,22 +37,23 @@ describe('User profiles API', () => { await suggestUserProfiles({ http, name: 'elastic', - owner: [GENERAL_CASES_OWNER], + owners: [GENERAL_CASES_OWNER], signal: abortCtrl.signal, }); expect(http.post).toHaveBeenCalledWith('/internal/cases/_suggest_user_profiles', { - body: '{"name":"elastic","size":10,"owner":["cases"]}', + body: '{"name":"elastic","size":10,"owners":["cases"]}', signal: abortCtrl.signal, }); }); }); describe('bulkGetUserProfiles', () => { - const { security } = createStartServicesMock(); + let security: SecurityPluginStart; beforeEach(() => { jest.clearAllMocks(); + security = securityMock.createStart(); security.userProfiles.bulkGet = jest.fn().mockResolvedValue(userProfiles); }); @@ -63,7 +66,7 @@ describe('User profiles API', () => { expect(res).toEqual(userProfiles); }); - it('calls http.post correctly', async () => { + it('calls bulkGet correctly', async () => { await bulkGetUserProfiles({ security, uids: userProfilesIds, @@ -79,4 +82,34 @@ describe('User profiles API', () => { }); }); }); + + describe('getCurrentUserProfile', () => { + let security: SecurityPluginStart; + + const currentProfile = userProfiles[0]; + + beforeEach(() => { + jest.clearAllMocks(); + security = securityMock.createStart(); + security.userProfiles.getCurrent = jest.fn().mockResolvedValue(currentProfile); + }); + + it('returns the current user profile correctly', async () => { + const res = await getCurrentUserProfile({ + security, + }); + + expect(res).toEqual(currentProfile); + }); + + it('calls getCurrent correctly', async () => { + await getCurrentUserProfile({ + security, + }); + + expect(security.userProfiles.getCurrent).toHaveBeenCalledWith({ + dataPath: 'avatar', + }); + }); + }); }); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/api.ts b/x-pack/plugins/cases/public/containers/user_profiles/api.ts index 6da84d19914238..cfd1c04d0afbca 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/api.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/api.ts @@ -13,7 +13,7 @@ import { INTERNAL_SUGGEST_USER_PROFILES_URL, DEFAULT_USER_SIZE } from '../../../ export interface SuggestUserProfilesArgs { http: HttpStart; name: string; - owner: string[]; + owners: string[]; signal: AbortSignal; size?: number; } @@ -22,11 +22,11 @@ export const suggestUserProfiles = async ({ http, name, size = DEFAULT_USER_SIZE, - owner, + owners, signal, }: SuggestUserProfilesArgs): Promise<UserProfile[]> => { const response = await http.post<UserProfile[]>(INTERNAL_SUGGEST_USER_PROFILES_URL, { - body: JSON.stringify({ name, size, owner }), + body: JSON.stringify({ name, size, owners }), signal, }); @@ -42,5 +42,19 @@ export const bulkGetUserProfiles = async ({ security, uids, }: BulkGetUserProfilesArgs): Promise<UserProfile[]> => { + if (uids.length === 0) { + return []; + } + return security.userProfiles.bulkGet({ uids: new Set(uids), dataPath: 'avatar' }); }; + +export interface GetCurrentUserProfileArgs { + security: SecurityPluginStart; +} + +export const getCurrentUserProfile = async ({ + security, +}: GetCurrentUserProfileArgs): Promise<UserProfile> => { + return security.userProfiles.getCurrent({ dataPath: 'avatar' }); +}; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts new file mode 100644 index 00000000000000..db4527ae31e436 --- /dev/null +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.test.ts @@ -0,0 +1,113 @@ +/* + * 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 { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { renderHook } from '@testing-library/react-hooks'; +import { userProfiles, userProfilesMap } from './api.mock'; +import { useAssignees } from './use_assignees'; + +describe('useAssignees', () => { + it('returns an empty array when the caseAssignees is empty', () => { + const { result } = renderHook(() => + useAssignees({ caseAssignees: [], userProfiles: new Map(), currentUserProfile: undefined }) + ); + + expect(result.current.allAssignees).toHaveLength(0); + expect(result.current.assigneesWithProfiles).toHaveLength(0); + expect(result.current.assigneesWithoutProfiles).toHaveLength(0); + }); + + it('returns all items in the with profiles array when they have profiles', () => { + const { result } = renderHook(() => + useAssignees({ + caseAssignees: userProfiles.map((profile) => ({ uid: profile.uid })), + userProfiles: userProfilesMap, + currentUserProfile: undefined, + }) + ); + + expect(result.current.assigneesWithoutProfiles).toHaveLength(0); + expect(result.current.allAssignees).toEqual(result.current.assigneesWithProfiles); + expect(result.current.allAssignees).toEqual(userProfiles.map(asAssigneeWithProfile)); + }); + + it('returns a sorted list of assignees with profiles', () => { + const unsorted = [...userProfiles].reverse(); + const { result } = renderHook(() => + useAssignees({ + caseAssignees: unsorted.map((profile) => ({ uid: profile.uid })), + userProfiles: userProfilesMap, + currentUserProfile: undefined, + }) + ); + + expect(result.current.assigneesWithoutProfiles).toHaveLength(0); + expect(result.current.allAssignees).toEqual(result.current.assigneesWithProfiles); + expect(result.current.allAssignees).toEqual(userProfiles.map(asAssigneeWithProfile)); + }); + + it('returns all items in the without profiles array when they do not have profiles', () => { + const unknownProfiles = [{ uid: '1' }, { uid: '2' }]; + const { result } = renderHook(() => + useAssignees({ + caseAssignees: unknownProfiles, + userProfiles: userProfilesMap, + currentUserProfile: undefined, + }) + ); + + expect(result.current.assigneesWithoutProfiles).toHaveLength(2); + expect(result.current.assigneesWithoutProfiles).toEqual(unknownProfiles); + expect(result.current.allAssignees).toEqual(unknownProfiles); + }); + + it('returns 1 user with a valid profile and 1 user with no profile and combines them in the all field', () => { + const assignees = [{ uid: '1' }, { uid: userProfiles[0].uid }]; + const { result } = renderHook(() => + useAssignees({ + caseAssignees: assignees, + userProfiles: userProfilesMap, + currentUserProfile: undefined, + }) + ); + + expect(result.current.assigneesWithProfiles).toHaveLength(1); + expect(result.current.assigneesWithoutProfiles).toHaveLength(1); + expect(result.current.allAssignees).toHaveLength(2); + + expect(result.current.assigneesWithProfiles).toEqual([asAssigneeWithProfile(userProfiles[0])]); + expect(result.current.assigneesWithoutProfiles).toEqual([{ uid: '1' }]); + expect(result.current.allAssignees).toEqual([ + asAssigneeWithProfile(userProfiles[0]), + { uid: '1' }, + ]); + }); + + it('returns assignees with profiles with the current user at the front', () => { + const { result } = renderHook(() => + useAssignees({ + caseAssignees: userProfiles, + userProfiles: userProfilesMap, + currentUserProfile: userProfiles[2], + }) + ); + + expect(result.current.assigneesWithProfiles).toHaveLength(3); + expect(result.current.allAssignees).toHaveLength(3); + + const asAssignees = userProfiles.map(asAssigneeWithProfile); + + expect(result.current.assigneesWithProfiles).toEqual([ + asAssignees[2], + asAssignees[0], + asAssignees[1], + ]); + expect(result.current.allAssignees).toEqual([asAssignees[2], asAssignees[0], asAssignees[1]]); + }); +}); + +const asAssigneeWithProfile = (profile: UserProfileWithAvatar) => ({ uid: profile.uid, profile }); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts new file mode 100644 index 00000000000000..2e1bb0a61dbdab --- /dev/null +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_assignees.ts @@ -0,0 +1,68 @@ +/* + * 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 { UserProfileWithAvatar } from '@kbn/user-profile-components'; +import { useMemo } from 'react'; +import { CaseAssignees } from '../../../common/api'; +import { CurrentUserProfile } from '../../components/types'; +import { bringCurrentUserToFrontAndSort } from '../../components/user_profiles/sort'; +import { Assignee, AssigneeWithProfile } from '../../components/user_profiles/types'; + +interface PartitionedAssignees { + usersWithProfiles: UserProfileWithAvatar[]; + usersWithoutProfiles: Assignee[]; +} + +export const useAssignees = ({ + caseAssignees, + userProfiles, + currentUserProfile, +}: { + caseAssignees: CaseAssignees; + userProfiles: Map<string, UserProfileWithAvatar>; + currentUserProfile: CurrentUserProfile; +}): { + assigneesWithProfiles: AssigneeWithProfile[]; + assigneesWithoutProfiles: Assignee[]; + allAssignees: Assignee[]; +} => { + const { assigneesWithProfiles, assigneesWithoutProfiles } = useMemo(() => { + const { usersWithProfiles, usersWithoutProfiles } = caseAssignees.reduce<PartitionedAssignees>( + (acc, assignee) => { + const profile = userProfiles.get(assignee.uid); + + if (profile) { + acc.usersWithProfiles.push(profile); + } else { + acc.usersWithoutProfiles.push({ uid: assignee.uid }); + } + + return acc; + }, + { usersWithProfiles: [], usersWithoutProfiles: [] } + ); + + const orderedProf = bringCurrentUserToFrontAndSort(currentUserProfile, usersWithProfiles); + + const assigneesWithProfile2 = orderedProf?.map((profile) => ({ uid: profile.uid, profile })); + return { + assigneesWithProfiles: assigneesWithProfile2 ?? [], + assigneesWithoutProfiles: usersWithoutProfiles, + }; + }, [caseAssignees, currentUserProfile, userProfiles]); + + const allAssignees = useMemo( + () => [...assigneesWithProfiles, ...assigneesWithoutProfiles], + [assigneesWithProfiles, assigneesWithoutProfiles] + ); + + return { + assigneesWithProfiles, + assigneesWithoutProfiles, + allAssignees, + }; +}; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts index 7591bf394d5c13..af0482f41b25ac 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.test.ts @@ -6,15 +6,18 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { useToasts } from '../../common/lib/kibana'; +import { useToasts, useKibana } from '../../common/lib/kibana'; import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; import * as api from './api'; import { useBulkGetUserProfiles } from './use_bulk_get_user_profiles'; import { userProfilesIds } from './api.mock'; +import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; jest.mock('../../common/lib/kibana'); jest.mock('./api'); +const useKibanaMock = useKibana as jest.Mock; + describe('useBulkGetUserProfiles', () => { const props = { uids: userProfilesIds, @@ -28,10 +31,13 @@ describe('useBulkGetUserProfiles', () => { beforeEach(() => { appMockRender = createAppMockRenderer(); jest.clearAllMocks(); + useKibanaMock.mockReturnValue({ + services: { ...createStartServicesMock() }, + }); }); it('calls bulkGetUserProfiles with correct arguments', async () => { - const spyOnSuggestUserProfiles = jest.spyOn(api, 'bulkGetUserProfiles'); + const spyOnBulkGetUserProfiles = jest.spyOn(api, 'bulkGetUserProfiles'); const { result, waitFor } = renderHook(() => useBulkGetUserProfiles(props), { wrapper: appMockRender.AppWrapper, @@ -39,16 +45,59 @@ describe('useBulkGetUserProfiles', () => { await waitFor(() => result.current.isSuccess); - expect(spyOnSuggestUserProfiles).toBeCalledWith({ + expect(spyOnBulkGetUserProfiles).toBeCalledWith({ ...props, security: expect.anything(), }); }); + it('returns a mapping with user profiles', async () => { + const { result, waitFor } = renderHook(() => useBulkGetUserProfiles(props), { + wrapper: appMockRender.AppWrapper, + }); + + await waitFor(() => result.current.isSuccess); + + expect(result.current.data).toMatchInlineSnapshot(` + Map { + "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0" => Object { + "data": Object {}, + "enabled": true, + "uid": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0", + "user": Object { + "email": "damaged_raccoon@elastic.co", + "full_name": "Damaged Raccoon", + "username": "damaged_raccoon", + }, + }, + "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0" => Object { + "data": Object {}, + "enabled": true, + "uid": "u_A_tM4n0wPkdiQ9smmd8o0Hr_h61XQfu8aRPh9GMoRoc_0", + "user": Object { + "email": "physical_dinosaur@elastic.co", + "full_name": "Physical Dinosaur", + "username": "physical_dinosaur", + }, + }, + "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0" => Object { + "data": Object {}, + "enabled": true, + "uid": "u_9xDEQqUqoYCnFnPPLq5mIRHKL8gBTo_NiKgOnd5gGk0_0", + "user": Object { + "email": "wet_dingo@elastic.co", + "full_name": "Wet Dingo", + "username": "wet_dingo", + }, + }, + } + `); + }); + it('shows a toast error message when an error occurs in the response', async () => { - const spyOnSuggestUserProfiles = jest.spyOn(api, 'bulkGetUserProfiles'); + const spyOnBulkGetUserProfiles = jest.spyOn(api, 'bulkGetUserProfiles'); - spyOnSuggestUserProfiles.mockImplementation(() => { + spyOnBulkGetUserProfiles.mockImplementation(() => { throw new Error('Something went wrong'); }); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts index 78c310462f77e2..de180b5970f3b7 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_bulk_get_user_profiles.ts @@ -6,24 +6,33 @@ */ import { useQuery, UseQueryResult } from '@tanstack/react-query'; -import { UserProfile } from '@kbn/security-plugin/common'; +import { UserProfileWithAvatar } from '@kbn/user-profile-components'; import * as i18n from '../translations'; import { useKibana, useToasts } from '../../common/lib/kibana'; import { ServerError } from '../../types'; import { USER_PROFILES_CACHE_KEY, USER_PROFILES_BULK_GET_CACHE_KEY } from '../constants'; import { bulkGetUserProfiles } from './api'; +const profilesToMap = (profiles: UserProfileWithAvatar[]): Map<string, UserProfileWithAvatar> => + profiles.reduce<Map<string, UserProfileWithAvatar>>((acc, profile) => { + acc.set(profile.uid, profile); + return acc; + }, new Map<string, UserProfileWithAvatar>()); + export const useBulkGetUserProfiles = ({ uids }: { uids: string[] }) => { const { security } = useKibana().services; const toasts = useToasts(); - return useQuery<UserProfile[], ServerError>( + return useQuery<UserProfileWithAvatar[], ServerError, Map<string, UserProfileWithAvatar>>( [USER_PROFILES_CACHE_KEY, USER_PROFILES_BULK_GET_CACHE_KEY, uids], () => { return bulkGetUserProfiles({ security, uids }); }, { + select: profilesToMap, + retry: false, + keepPreviousData: true, onError: (error: ServerError) => { if (error.name !== 'AbortError') { toasts.addError( @@ -38,4 +47,7 @@ export const useBulkGetUserProfiles = ({ uids }: { uids: string[] }) => { ); }; -export type UseSuggestUserProfiles = UseQueryResult<UserProfile[], ServerError>; +export type UseBulkGetUserProfiles = UseQueryResult< + Map<string, UserProfileWithAvatar>, + ServerError +>; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts new file mode 100644 index 00000000000000..ebc896a480cb04 --- /dev/null +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts @@ -0,0 +1,97 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; +import { useToasts, useKibana } from '../../common/lib/kibana'; +import { createStartServicesMock } from '../../common/lib/kibana/kibana_react.mock'; +import { AppMockRenderer, createAppMockRenderer } from '../../common/mock'; +import * as api from './api'; +import { useGetCurrentUserProfile } from './use_get_current_user_profile'; + +jest.mock('../../common/lib/kibana'); +jest.mock('./api'); + +const useKibanaMock = useKibana as jest.Mock; + +describe('useGetCurrentUserProfile', () => { + const addSuccess = jest.fn(); + (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError: jest.fn() }); + + let appMockRender: AppMockRenderer; + + beforeEach(() => { + appMockRender = createAppMockRenderer(); + jest.clearAllMocks(); + useKibanaMock.mockReturnValue({ + services: { ...createStartServicesMock() }, + }); + }); + + it('calls getCurrentUserProfile with correct arguments', async () => { + const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); + + const { result, waitFor } = renderHook(() => useGetCurrentUserProfile(), { + wrapper: appMockRender.AppWrapper, + }); + + await waitFor(() => result.current.isSuccess); + + expect(spyOnGetCurrentUserProfile).toBeCalledWith({ + security: expect.anything(), + }); + }); + + it('shows a toast error message when an error occurs in the response', async () => { + const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); + + spyOnGetCurrentUserProfile.mockImplementation(() => { + throw new Error('Something went wrong'); + }); + + const addError = jest.fn(); + (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); + + const { result, waitFor } = renderHook(() => useGetCurrentUserProfile(), { + wrapper: appMockRender.AppWrapper, + }); + + await waitFor(() => result.current.isError); + + expect(addError).toHaveBeenCalled(); + }); + + it('does not show a toast error message when a 404 error is returned', async () => { + const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); + + spyOnGetCurrentUserProfile.mockImplementation(() => { + throw new MockServerError('profile not found', 404); + }); + + const addError = jest.fn(); + (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); + + const { result, waitFor } = renderHook(() => useGetCurrentUserProfile(), { + wrapper: appMockRender.AppWrapper, + }); + + await waitFor(() => result.current.isError); + + expect(addError).not.toHaveBeenCalled(); + }); +}); + +class MockServerError extends Error { + public readonly body: { + statusCode: number; + }; + + constructor(message?: string, statusCode: number = 200) { + super(message); + this.name = this.constructor.name; + this.body = { statusCode }; + } +} diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts new file mode 100644 index 00000000000000..37c29fa0b2d01c --- /dev/null +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.ts @@ -0,0 +1,44 @@ +/* + * 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 { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { UserProfile } from '@kbn/security-plugin/common'; +import * as i18n from '../translations'; +import { useKibana, useToasts } from '../../common/lib/kibana'; +import { ServerError } from '../../types'; +import { USER_PROFILES_CACHE_KEY, USER_PROFILES_GET_CURRENT_CACHE_KEY } from '../constants'; +import { getCurrentUserProfile } from './api'; + +export const useGetCurrentUserProfile = () => { + const { security } = useKibana().services; + + const toasts = useToasts(); + + return useQuery<UserProfile, ServerError>( + [USER_PROFILES_CACHE_KEY, USER_PROFILES_GET_CURRENT_CACHE_KEY], + () => { + return getCurrentUserProfile({ security }); + }, + { + retry: false, + onError: (error: ServerError) => { + // Anonymous users (users authenticated via a proxy or configured in the kibana config) will result in a 404 + // from the security plugin. If this happens we'll silence the error and operate without the current user profile + if (error.name !== 'AbortError' && error.body?.statusCode !== 404) { + toasts.addError( + error.body && error.body.message ? new Error(error.body.message) : error, + { + title: i18n.ERROR_TITLE, + } + ); + } + }, + } + ); +}; + +export type UseGetCurrentUserProfile = UseQueryResult<UserProfile, ServerError>; diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts index ef5fe32a23dff8..2d4482b94a9c64 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.test.ts @@ -18,7 +18,7 @@ jest.mock('./api'); describe('useSuggestUserProfiles', () => { const props = { name: 'elastic', - owner: [GENERAL_CASES_OWNER], + owners: [GENERAL_CASES_OWNER], }; const addSuccess = jest.fn(); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts index 6c83f853b2624e..26e03d0163c8e7 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_suggest_user_profiles.ts @@ -9,24 +9,42 @@ import { useState } from 'react'; import { useQuery, UseQueryResult } from '@tanstack/react-query'; import useDebounce from 'react-use/lib/useDebounce'; import { UserProfile } from '@kbn/security-plugin/common'; -import { DEFAULT_USER_SIZE } from '../../../common/constants'; +import { noop } from 'lodash'; +import { DEFAULT_USER_SIZE, SEARCH_DEBOUNCE_MS } from '../../../common/constants'; import * as i18n from '../translations'; import { useKibana, useToasts } from '../../common/lib/kibana'; import { ServerError } from '../../types'; import { USER_PROFILES_CACHE_KEY, USER_PROFILES_SUGGEST_CACHE_KEY } from '../constants'; import { suggestUserProfiles, SuggestUserProfilesArgs } from './api'; -const DEBOUNCE_MS = 500; +type Props = Omit<SuggestUserProfilesArgs, 'signal' | 'http'> & { onDebounce?: () => void }; + +/** + * Time in ms until the data become stale. + * We set the stale time to one minute + * to prevent fetching the same queries + * while the user is typing. + */ + +const STALE_TIME = 1000 * 60; export const useSuggestUserProfiles = ({ name, - owner, + owners, size = DEFAULT_USER_SIZE, -}: Omit<SuggestUserProfilesArgs, 'signal' | 'http'>) => { + onDebounce = noop, +}: Props) => { const { http } = useKibana().services; const [debouncedName, setDebouncedName] = useState(name); - useDebounce(() => setDebouncedName(name), DEBOUNCE_MS, [name]); + useDebounce( + () => { + setDebouncedName(name); + onDebounce(); + }, + SEARCH_DEBOUNCE_MS, + [name] + ); const toasts = useToasts(); @@ -34,20 +52,22 @@ export const useSuggestUserProfiles = ({ [ USER_PROFILES_CACHE_KEY, USER_PROFILES_SUGGEST_CACHE_KEY, - { name: debouncedName, owner, size }, + { name: debouncedName, owners, size }, ], () => { const abortCtrlRef = new AbortController(); return suggestUserProfiles({ http, name: debouncedName, - owner, + owners, size, signal: abortCtrlRef.signal, }); }, { retry: false, + keepPreviousData: true, + staleTime: STALE_TIME, onError: (error: ServerError) => { if (error.name !== 'AbortError') { toasts.addError( diff --git a/x-pack/plugins/cases/public/utils/permissions.test.ts b/x-pack/plugins/cases/public/utils/permissions.test.ts new file mode 100644 index 00000000000000..66e63e6950dd4c --- /dev/null +++ b/x-pack/plugins/cases/public/utils/permissions.test.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 { noCasesPermissions, readCasesPermissions } from '../common/mock'; +import { getAllPermissionsExceptFrom, isReadOnlyPermissions } from './permissions'; + +describe('permissions', () => { + describe('isReadOnlyPermissions', () => { + const tests = [['update'], ['create'], ['delete'], ['push'], ['all']]; + + it('returns true if the user has only read permissions', async () => { + expect(isReadOnlyPermissions(readCasesPermissions())).toBe(true); + }); + + it('returns true if the user has not read permissions', async () => { + expect(isReadOnlyPermissions(noCasesPermissions())).toBe(false); + }); + + it.each(tests)( + 'returns false if the user has permission %s=true and read=true', + async (permission) => { + const noPermissions = noCasesPermissions(); + expect(isReadOnlyPermissions({ ...noPermissions, [permission]: true })).toBe(false); + } + ); + }); + + describe('getAllPermissionsExceptFrom', () => { + it('returns the correct permissions', async () => { + expect(getAllPermissionsExceptFrom('create')).toEqual(['read', 'update', 'delete', 'push']); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/utils/permissions.ts b/x-pack/plugins/cases/public/utils/permissions.ts index 827535d484588a..75e15f8859e580 100644 --- a/x-pack/plugins/cases/public/utils/permissions.ts +++ b/x-pack/plugins/cases/public/utils/permissions.ts @@ -17,3 +17,10 @@ export const isReadOnlyPermissions = (permissions: CasesPermissions) => { permissions.read ); }; + +type CasePermission = Exclude<keyof CasesPermissions, 'all'>; + +export const allCasePermissions: CasePermission[] = ['create', 'read', 'update', 'delete', 'push']; + +export const getAllPermissionsExceptFrom = (capToExclude: CasePermission): CasePermission[] => + allCasePermissions.filter((permission) => permission !== capToExclude) as CasePermission[]; diff --git a/x-pack/plugins/cases/server/features.ts b/x-pack/plugins/cases/server/features.ts index d2ddc6a1030a04..9f92c7d9398a6b 100644 --- a/x-pack/plugins/cases/server/features.ts +++ b/x-pack/plugins/cases/server/features.ts @@ -55,7 +55,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { ui: capabilities.all, }, read: { - api: ['bulkGetUserProfiles'], + api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], cases: { read: [APP_ID], }, diff --git a/x-pack/plugins/cases/server/services/user_profiles/index.ts b/x-pack/plugins/cases/server/services/user_profiles/index.ts index 36bc0c439a79e5..4ba9eb630e53f1 100644 --- a/x-pack/plugins/cases/server/services/user_profiles/index.ts +++ b/x-pack/plugins/cases/server/services/user_profiles/index.ts @@ -19,8 +19,8 @@ import { excess, SuggestUserProfilesRequestRt, throwErrors } from '../../../comm import { Operations } from '../../authorization'; import { createCaseError } from '../../common/error'; -const MAX_SUGGESTION_SIZE = 100; -const MIN_SUGGESTION_SIZE = 0; +const MAX_PROFILES_SIZE = 100; +const MIN_PROFILES_SIZE = 0; interface UserProfileOptions { securityPluginSetup?: SecurityPluginSetup; @@ -41,6 +41,32 @@ export class UserProfileService { this.options = options; } + private static suggestUsers({ + securityPluginStart, + spaceId, + searchTerm, + size, + owners, + }: { + securityPluginStart: SecurityPluginStart; + spaceId: string; + searchTerm: string; + size?: number; + owners: string[]; + }) { + return securityPluginStart.userProfiles.suggest({ + name: searchTerm, + size, + dataPath: 'avatar', + requiredPrivileges: { + spaceId, + privileges: { + kibana: UserProfileService.buildRequiredPrivileges(owners, securityPluginStart), + }, + }, + }); + } + public async suggest(request: KibanaRequest): Promise<UserProfile[]> { const params = pipe( excess(SuggestUserProfilesRequestRt).decode(request.body), @@ -61,29 +87,20 @@ export class UserProfileService { securityPluginStart: this.options.securityPluginStart, }; - /** - * The limit of 100 helps prevent DDoS attacks and is also enforced by the security plugin. - */ - if (size !== undefined && (size > MAX_SUGGESTION_SIZE || size < MIN_SUGGESTION_SIZE)) { - throw Boom.badRequest('size must be between 0 and 100'); - } + UserProfileService.validateSizeParam(size); - if (!UserProfileService.isSecurityEnabled(securityPluginFields)) { + if (!UserProfileService.isSecurityEnabled(securityPluginFields) || owners.length <= 0) { return []; } const { securityPluginStart } = securityPluginFields; - return securityPluginStart.userProfiles.suggest({ - name, + return UserProfileService.suggestUsers({ + searchTerm: name, size, - dataPath: 'avatar', - requiredPrivileges: { - spaceId: spaces.spacesService.getSpaceId(request), - privileges: { - kibana: UserProfileService.buildRequiredPrivileges(owners, securityPluginStart), - }, - }, + owners, + securityPluginStart, + spaceId: spaces.spacesService.getSpaceId(request), }); } catch (error) { throw createCaseError({ @@ -94,6 +111,15 @@ export class UserProfileService { } } + private static validateSizeParam(size?: number) { + /** + * The limit of 100 helps prevent DDoS attacks and is also enforced by the security plugin. + */ + if (size !== undefined && (size > MAX_PROFILES_SIZE || size < MIN_PROFILES_SIZE)) { + throw Boom.badRequest('size must be between 0 and 100'); + } + } + private static isSecurityEnabled(fields: { securityPluginSetup?: SecurityPluginSetup; securityPluginStart?: SecurityPluginStart; diff --git a/x-pack/plugins/ml/public/application/util/dependency_cache.ts b/x-pack/plugins/ml/public/application/util/dependency_cache.ts index 3680f8b63b0c96..0b78fb460ed859 100644 --- a/x-pack/plugins/ml/public/application/util/dependency_cache.ts +++ b/x-pack/plugins/ml/public/application/util/dependency_cache.ts @@ -24,7 +24,7 @@ import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/ import type { DashboardStart } from '@kbn/dashboard-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; -import type { SecurityPluginSetup } from '@kbn/security-plugin/public'; +import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import type { MapsStartApi } from '@kbn/maps-plugin/public'; import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public'; @@ -43,7 +43,7 @@ export interface DependencyCache { savedObjectsClient: SavedObjectsClientContract | null; application: ApplicationStart | null; http: HttpStart | null; - security: SecurityPluginSetup | undefined | null; + security: SecurityPluginStart | undefined | null; i18n: I18nStart | null; dashboard: DashboardStart | null; maps: MapsStartApi | null; diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 9d084708e6529b..3037d841803493 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -30,7 +30,7 @@ import type { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/publ import type { LicenseManagementUIPluginSetup } from '@kbn/license-management-plugin/public'; import type { LicensingPluginSetup } from '@kbn/licensing-plugin/public'; -import type { SecurityPluginSetup } from '@kbn/security-plugin/public'; +import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import type { MapsStartApi, MapsSetupApi } from '@kbn/maps-plugin/public'; import { @@ -66,10 +66,10 @@ export interface MlStartDependencies { charts: ChartsPluginStart; lens?: LensPublicStart; cases?: CasesUiStart; + security: SecurityPluginStart; } export interface MlSetupDependencies { - security?: SecurityPluginSetup; maps?: MapsSetupApi; licensing: LicensingPluginSetup; management?: ManagementSetup; @@ -119,7 +119,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> { unifiedSearch: pluginsStart.unifiedSearch, dashboard: pluginsStart.dashboard, share: pluginsStart.share, - security: pluginsSetup.security, + security: pluginsStart.security, licensing: pluginsSetup.licensing, management: pluginsSetup.management, licenseManagement: pluginsSetup.licenseManagement, diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts index 4a1f91719bca64..1d9d3cbf455f10 100644 --- a/x-pack/plugins/observability/server/plugin.ts +++ b/x-pack/plugins/observability/server/plugin.ts @@ -74,7 +74,7 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> { ui: casesCapabilities.all, }, read: { - api: ['bulkGetUserProfiles'], + api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], app: [casesFeatureId, 'kibana'], catalogue: [observabilityFeatureId], cases: { diff --git a/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts index 0b53557dbcd036..81ae0d5b40fd75 100644 --- a/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts @@ -17,8 +17,6 @@ import { ALL_CASES_OPEN_CASES_STATS, ALL_CASES_OPENED_ON, ALL_CASES_PAGE_TITLE, - ALL_CASES_REPORTER, - ALL_CASES_REPORTERS_COUNT, ALL_CASES_SERVICE_NOW_INCIDENT, ALL_CASES_TAGS, ALL_CASES_TAGS_COUNT, @@ -85,10 +83,8 @@ describe('Cases', () => { cy.get(ALL_CASES_CLOSED_CASES_STATS).should('have.text', '0'); cy.get(ALL_CASES_IN_PROGRESS_CASES_STATS).should('have.text', '0'); cy.get(ALL_CASES_OPEN_CASES_COUNT).should('have.text', 'Open (1)'); - cy.get(ALL_CASES_REPORTERS_COUNT).should('have.text', 'Reporter1'); cy.get(ALL_CASES_TAGS_COUNT).should('have.text', 'Tags2'); cy.get(ALL_CASES_NAME).should('have.text', this.mycase.name); - cy.get(ALL_CASES_REPORTER).should('have.text', 'e'); (this.mycase as TestCase).tags.forEach((tag) => { cy.get(ALL_CASES_TAGS(tag)).should('have.text', tag); }); diff --git a/x-pack/plugins/security_solution/cypress/screens/all_cases.ts b/x-pack/plugins/security_solution/cypress/screens/all_cases.ts index 3f5bcb912ee442..8109bc31e07ada 100644 --- a/x-pack/plugins/security_solution/cypress/screens/all_cases.ts +++ b/x-pack/plugins/security_solution/cypress/screens/all_cases.ts @@ -34,11 +34,6 @@ export const ALL_CASES_OPENED_ON = '[data-test-subj="case-table-column-createdAt export const ALL_CASES_PAGE_TITLE = '[data-test-subj="header-page-title"]'; -export const ALL_CASES_REPORTER = '[data-test-subj="case-table-column-createdBy"]'; - -export const ALL_CASES_REPORTERS_COUNT = - '[data-test-subj="options-filter-popover-button-Reporter"]'; - export const ALL_CASES_SERVICE_NOW_INCIDENT = '[data-test-subj="case-table-column-external-notPushed"]'; diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/cases/import_case.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/cases/import_case.spec.ts index 13afc4c7889eb6..4eecc36fe928aa 100644 --- a/x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/cases/import_case.spec.ts +++ b/x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/cases/import_case.spec.ts @@ -13,7 +13,6 @@ import { ALL_CASES_NOT_PUSHED, ALL_CASES_NUMBER_OF_ALERTS, ALL_CASES_OPEN_CASES_STATS, - ALL_CASES_REPORTER, ALL_CASES_IN_PROGRESS_STATUS, } from '../../../screens/all_cases'; import { @@ -108,7 +107,6 @@ describe('Import case after upgrade', () => { it('Displays the correct case details on the cases page', () => { cy.get(ALL_CASES_NAME).should('have.text', importedCase.title); - cy.get(ALL_CASES_REPORTER).should('have.text', importedCase.initial); cy.get(ALL_CASES_NUMBER_OF_ALERTS).should('have.text', importedCase.numberOfAlerts); cy.get(ALL_CASES_COMMENTS_COUNT).should('have.text', importedCase.numberOfComments); cy.get(ALL_CASES_NOT_PUSHED).should('be.visible'); diff --git a/x-pack/plugins/security_solution/server/features.ts b/x-pack/plugins/security_solution/server/features.ts index c962e9fbf2d877..2a794285b52b79 100644 --- a/x-pack/plugins/security_solution/server/features.ts +++ b/x-pack/plugins/security_solution/server/features.ts @@ -45,7 +45,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { ui: casesCapabilities.all, }, read: { - api: ['bulkGetUserProfiles'], + api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], app: [CASES_FEATURE_ID, 'kibana'], catalogue: [APP_ID], cases: { diff --git a/x-pack/test/api_integration/apis/cases/bulk_get_user_profiles.ts b/x-pack/test/api_integration/apis/cases/bulk_get_user_profiles.ts index a8aad06c999d0c..8de4b3dc32a0c6 100644 --- a/x-pack/test/api_integration/apis/cases/bulk_get_user_profiles.ts +++ b/x-pack/test/api_integration/apis/cases/bulk_get_user_profiles.ts @@ -11,11 +11,11 @@ import { APP_ID as SECURITY_SOLUTION_APP_ID } from '@kbn/security-solution-plugi import { observabilityFeatureId as OBSERVABILITY_APP_ID } from '@kbn/observability-plugin/common'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { deleteAllCaseItems } from '../../../cases_api_integration/common/lib/utils'; import { - deleteAllCaseItems, + bulkGetUserProfiles, suggestUserProfiles, -} from '../../../cases_api_integration/common/lib/utils'; -import { bulkGetUserProfiles } from '../../../cases_api_integration/common/lib/user_profiles'; +} from '../../../cases_api_integration/common/lib/user_profiles'; import { casesAllUser, casesReadUser, diff --git a/x-pack/test/api_integration/apis/cases/index.ts b/x-pack/test/api_integration/apis/cases/index.ts index 3bb170937bafcb..5b9d9d1bfe918e 100644 --- a/x-pack/test/api_integration/apis/cases/index.ts +++ b/x-pack/test/api_integration/apis/cases/index.ts @@ -10,7 +10,7 @@ import { deleteUsersAndRoles, } from '../../../cases_api_integration/common/lib/authentication'; -import { loginUsers } from '../../../cases_api_integration/common/lib/utils'; +import { loginUsers } from '../../../cases_api_integration/common/lib/user_profiles'; import { casesAllUser, obsCasesAllUser, secAllUser, users } from './common/users'; import { roles } from './common/roles'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/cases/suggest_user_profiles.ts b/x-pack/test/api_integration/apis/cases/suggest_user_profiles.ts index 72680ef786e9ed..dca999ab689027 100644 --- a/x-pack/test/api_integration/apis/cases/suggest_user_profiles.ts +++ b/x-pack/test/api_integration/apis/cases/suggest_user_profiles.ts @@ -11,15 +11,16 @@ import { APP_ID as SECURITY_SOLUTION_APP_ID } from '@kbn/security-solution-plugi import { observabilityFeatureId as OBSERVABILITY_APP_ID } from '@kbn/observability-plugin/common'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { - deleteAllCaseItems, - suggestUserProfiles, -} from '../../../cases_api_integration/common/lib/utils'; +import { deleteAllCaseItems } from '../../../cases_api_integration/common/lib/utils'; +import { suggestUserProfiles } from '../../../cases_api_integration/common/lib/user_profiles'; import { casesAllUser, casesOnlyDeleteUser, + casesReadUser, obsCasesAllUser, obsCasesOnlyDeleteUser, + obsCasesReadUser, + secAllCasesNoneUser, secAllCasesReadUser, secAllUser, } from './common/users'; @@ -33,27 +34,34 @@ export default ({ getService }: FtrProviderContext): void => { await deleteAllCaseItems(es); }); - for (const { user, owner } of [ - { user: secAllUser, owner: SECURITY_SOLUTION_APP_ID }, - { user: casesAllUser, owner: CASES_APP_ID }, - { user: obsCasesAllUser, owner: OBSERVABILITY_APP_ID }, + for (const { user, searchTerm, owner } of [ + { user: secAllUser, searchTerm: secAllUser.username, owner: SECURITY_SOLUTION_APP_ID }, + { + user: secAllCasesReadUser, + searchTerm: secAllUser.username, + owner: SECURITY_SOLUTION_APP_ID, + }, + { user: casesAllUser, searchTerm: casesAllUser.username, owner: CASES_APP_ID }, + { user: casesReadUser, searchTerm: casesAllUser.username, owner: CASES_APP_ID }, + { user: obsCasesAllUser, searchTerm: obsCasesAllUser.username, owner: OBSERVABILITY_APP_ID }, + { user: obsCasesReadUser, searchTerm: obsCasesAllUser.username, owner: OBSERVABILITY_APP_ID }, ]) { it(`User ${ user.username } with roles(s) ${user.roles.join()} can retrieve user profile suggestions`, async () => { const profiles = await suggestUserProfiles({ supertest: supertestWithoutAuth, - req: { name: user.username, owners: [owner], size: 1 }, + req: { name: searchTerm, owners: [owner], size: 1 }, auth: { user, space: null }, }); expect(profiles.length).to.be(1); - expect(profiles[0].user.username).to.eql(user.username); + expect(profiles[0].user.username).to.eql(searchTerm); }); } for (const { user, owner } of [ - { user: secAllCasesReadUser, owner: SECURITY_SOLUTION_APP_ID }, + { user: secAllCasesNoneUser, owner: SECURITY_SOLUTION_APP_ID }, { user: casesOnlyDeleteUser, owner: CASES_APP_ID }, { user: obsCasesOnlyDeleteUser, owner: OBSERVABILITY_APP_ID }, ]) { diff --git a/x-pack/test/cases_api_integration/common/fixtures/plugins/observability/server/plugin.ts b/x-pack/test/cases_api_integration/common/fixtures/plugins/observability/server/plugin.ts index 9dcdc8a26af0e6..fb872f775c5bb6 100644 --- a/x-pack/test/cases_api_integration/common/fixtures/plugins/observability/server/plugin.ts +++ b/x-pack/test/cases_api_integration/common/fixtures/plugins/observability/server/plugin.ts @@ -31,7 +31,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu cases: ['observabilityFixture'], privileges: { all: { - api: ['casesSuggestUserProfiles'], + api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], app: ['kibana'], cases: { all: ['observabilityFixture'], @@ -43,6 +43,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu ui: [], }, read: { + api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], app: ['kibana'], cases: { read: ['observabilityFixture'], diff --git a/x-pack/test/cases_api_integration/common/fixtures/plugins/security_solution/server/plugin.ts b/x-pack/test/cases_api_integration/common/fixtures/plugins/security_solution/server/plugin.ts index 36917706d719ce..b22674d66db4cc 100644 --- a/x-pack/test/cases_api_integration/common/fixtures/plugins/security_solution/server/plugin.ts +++ b/x-pack/test/cases_api_integration/common/fixtures/plugins/security_solution/server/plugin.ts @@ -54,7 +54,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu ui: [], }, read: { - api: ['bulkGetUserProfiles'], + api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], app: ['kibana'], cases: { read: ['securitySolutionFixture'], diff --git a/x-pack/test/cases_api_integration/common/lib/authentication/index.ts b/x-pack/test/cases_api_integration/common/lib/authentication/index.ts index 5ca8ac3bcd9f74..65e82a2e4fbf39 100644 --- a/x-pack/test/cases_api_integration/common/lib/authentication/index.ts +++ b/x-pack/test/cases_api_integration/common/lib/authentication/index.ts @@ -10,7 +10,7 @@ import { Role, User, UserInfo } from './types'; import { obsOnly, secOnly, secOnlyNoDelete, secOnlyRead, users } from './users'; import { roles } from './roles'; import { spaces } from './spaces'; -import { loginUsers } from '../utils'; +import { loginUsers } from '../user_profiles'; export const getUserInfo = (user: User): UserInfo => ({ username: user.username, diff --git a/x-pack/test/cases_api_integration/common/lib/user_profiles.ts b/x-pack/test/cases_api_integration/common/lib/user_profiles.ts index e68de4418c9bfd..aefe3d0b1c8732 100644 --- a/x-pack/test/cases_api_integration/common/lib/user_profiles.ts +++ b/x-pack/test/cases_api_integration/common/lib/user_profiles.ts @@ -8,6 +8,9 @@ import type SuperTest from 'supertest'; import { UserProfileBulkGetParams, UserProfileServiceStart } from '@kbn/security-plugin/server'; +import { INTERNAL_SUGGEST_USER_PROFILES_URL } from '@kbn/cases-plugin/common/constants'; +import { SuggestUserProfilesRequest } from '@kbn/cases-plugin/common/api'; +import { UserProfileService } from '@kbn/cases-plugin/server/services'; import { superUser } from './authentication/users'; import { User } from './authentication/types'; import { getSpaceUrlPrefix } from './utils'; @@ -37,3 +40,45 @@ export const bulkGetUserProfiles = async ({ return profiles; }; + +export const suggestUserProfiles = async ({ + supertest, + req, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest<SuperTest.Test>; + req: SuggestUserProfilesRequest; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): ReturnType<UserProfileService['suggest']> => { + const { body: profiles } = await supertest + .post(`${getSpaceUrlPrefix(auth.space)}${INTERNAL_SUGGEST_USER_PROFILES_URL}`) + .auth(auth.user.username, auth.user.password) + .set('kbn-xsrf', 'true') + .send(req) + .expect(expectedHttpCode); + + return profiles; +}; + +export const loginUsers = async ({ + supertest, + users = [superUser], +}: { + supertest: SuperTest.SuperTest<SuperTest.Test>; + users?: User[]; +}) => { + for (const user of users) { + await supertest + .post('/internal/security/login') + .set('kbn-xsrf', 'xxx') + .send({ + providerType: 'basic', + providerName: 'basic', + currentURL: '/', + params: { username: user.username, password: user.password }, + }) + .expect(200); + } +}; diff --git a/x-pack/test/cases_api_integration/common/lib/utils.ts b/x-pack/test/cases_api_integration/common/lib/utils.ts index 85350fb43f1f27..1c801341a0e998 100644 --- a/x-pack/test/cases_api_integration/common/lib/utils.ts +++ b/x-pack/test/cases_api_integration/common/lib/utils.ts @@ -24,7 +24,6 @@ import { CASE_REPORTERS_URL, CASE_STATUS_URL, CASE_TAGS_URL, - INTERNAL_SUGGEST_USER_PROFILES_URL, } from '@kbn/cases-plugin/common/constants'; import { CasesConfigureRequest, @@ -54,7 +53,6 @@ import { BulkCreateCommentRequest, CommentType, CasesMetricsResponse, - SuggestUserProfilesRequest, } from '@kbn/cases-plugin/common/api'; import { getCaseUserActionUrl } from '@kbn/cases-plugin/common/api/helpers'; import { SignalHit } from '@kbn/security-solution-plugin/server/lib/detection_engine/signals/types'; @@ -62,7 +60,6 @@ import { ActionResult, FindActionResult } from '@kbn/actions-plugin/server/types import { ESCasesConfigureAttributes } from '@kbn/cases-plugin/server/services/configure/types'; import { ESCaseAttributes } from '@kbn/cases-plugin/server/services/cases/types'; import type { SavedObjectsRawDocSource } from '@kbn/core/server'; -import { UserProfileService } from '@kbn/cases-plugin/server/services'; import { User } from './authentication/types'; import { superUser } from './authentication/users'; import { getPostCaseRequest, postCaseReq } from './mock'; @@ -1348,45 +1345,3 @@ export const getReferenceFromEsResponse = ( esResponse: TransportResult<GetResponse<SavedObjectsRawDocSource>, unknown>, id: string ) => esResponse.body._source?.references?.find((r) => r.id === id); - -export const suggestUserProfiles = async ({ - supertest, - req, - expectedHttpCode = 200, - auth = { user: superUser, space: null }, -}: { - supertest: SuperTest.SuperTest<SuperTest.Test>; - req: SuggestUserProfilesRequest; - expectedHttpCode?: number; - auth?: { user: User; space: string | null }; -}): ReturnType<UserProfileService['suggest']> => { - const { body: profiles } = await supertest - .post(`${getSpaceUrlPrefix(auth.space)}${INTERNAL_SUGGEST_USER_PROFILES_URL}`) - .auth(auth.user.username, auth.user.password) - .set('kbn-xsrf', 'true') - .send(req) - .expect(expectedHttpCode); - - return profiles; -}; - -export const loginUsers = async ({ - supertest, - users = [superUser], -}: { - supertest: SuperTest.SuperTest<SuperTest.Test>; - users?: User[]; -}) => { - for (const user of users) { - await supertest - .post('/internal/security/login') - .set('kbn-xsrf', 'xxx') - .send({ - providerType: 'basic', - providerName: 'basic', - currentURL: '/', - params: { username: user.username, password: user.password }, - }) - .expect(200); - } -}; diff --git a/x-pack/test/cases_api_integration/common/lib/validation.ts b/x-pack/test/cases_api_integration/common/lib/validation.ts index c901631388f11b..a84c733586ec06 100644 --- a/x-pack/test/cases_api_integration/common/lib/validation.ts +++ b/x-pack/test/cases_api_integration/common/lib/validation.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { CaseResponse, CasesByAlertId } from '@kbn/cases-plugin/common/api'; +import { xorWith, isEqual } from 'lodash'; /** * Ensure that the result of the alerts API request matches with the cases created for the test. @@ -29,13 +30,12 @@ export function validateCasesFromAlertIDResponse( * Compares two arrays to determine if they are sort of equal. This function returns true if the arrays contain the same * elements but the ordering does not matter. */ -export function arraysToEqual(array1?: object[], array2?: object[]) { +export function arraysToEqual<T>(array1?: T[], array2?: T[]) { if (!array1 || !array2 || array1.length !== array2.length) { return false; } - const array1AsSet = new Set(array1); - return array2.every((item) => array1AsSet.has(item)); + return xorWith(array1, array2, isEqual).length === 0; } /** diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/assignees.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/assignees.ts index b92ddadc32c080..fbe2672c17cbef 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/assignees.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/assignees.ts @@ -10,13 +10,14 @@ import expect from '@kbn/expect'; import { findCasesResp, getPostCaseRequest, postCaseReq } from '../../../../common/lib/mock'; import { createCase, - suggestUserProfiles, getCase, findCases, updateCase, deleteAllCaseItems, } from '../../../../common/lib/utils'; +import { suggestUserProfiles } from '../../../../common/lib/user_profiles'; + import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { bulkGetUserProfiles } from '../../../../common/lib/user_profiles'; import { superUser } from '../../../../common/lib/authentication/users'; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts index 65f3a36cbe4877..3daa29c02b107b 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts @@ -238,9 +238,11 @@ export default ({ getService }: FtrProviderContext): void => { it('returns the correct fields', async () => { const postedCase = await createCase(supertest, postCaseReq); + // all fields that contain the UserRT definition must be included here (aka created_by, closed_by, and updated_by) + // see https://github.com/elastic/kibana/issues/139503 const queryFields: Array<keyof CaseResponse | Array<keyof CaseResponse>> = [ - 'title', - ['title', 'description'], + ['title', 'created_by', 'closed_by', 'updated_by'], + ['title', 'description', 'created_by', 'closed_by', 'updated_by'], ]; for (const fields of queryFields) { diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/suggest_user_profiles.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/suggest_user_profiles.ts index 177d5ffc06486d..f5feab6f045570 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/suggest_user_profiles.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/suggest_user_profiles.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { loginUsers, suggestUserProfiles } from '../../../../common/lib/utils'; +import { loginUsers, suggestUserProfiles } from '../../../../common/lib/user_profiles'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { superUser, @@ -21,6 +21,19 @@ export default function ({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('suggest_user_profiles', () => { + it('returns no suggestions when the owner is an empty array', async () => { + const profiles = await suggestUserProfiles({ + supertest: supertestWithoutAuth, + req: { + name: 'delete', + owners: [], + }, + auth: { user: superUser, space: 'space1' }, + }); + + expect(profiles.length).to.be(0); + }); + it('finds the profile for the user without deletion privileges', async () => { const profiles = await suggestUserProfiles({ supertest: supertestWithoutAuth, diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics_alerts.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics_alerts.ts index 1f58d4b72cea87..060b7dda22dea5 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics_alerts.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics_alerts.ts @@ -51,7 +51,7 @@ export default ({ getService }: FtrProviderContext): void => { { id: '7eb51035-5582-4cb8-9db2-5e71ef09aa5c', name: 'Host-123', count: 2 }, { id: '7eb51035-5582-4cb8-9db2-5e71ef09aa5d', name: 'Host-100', count: 2 }, ]) - ); + ).to.be(true); }); it('returns the user metrics', async () => { @@ -69,7 +69,7 @@ export default ({ getService }: FtrProviderContext): void => { { name: '7bgwxrbmcu', count: 1 }, { name: 'jf9e87gsut', count: 1 }, ]) - ); + ).to.be(true); }); it('returns both the host and user metrics', async () => { @@ -86,7 +86,7 @@ export default ({ getService }: FtrProviderContext): void => { { id: '7eb51035-5582-4cb8-9db2-5e71ef09aa5c', name: 'Host-123', count: 2 }, { id: '7eb51035-5582-4cb8-9db2-5e71ef09aa5d', name: 'Host-100', count: 2 }, ]) - ); + ).to.be(true); expect(metrics.alerts?.users?.total).to.be(4); expect( @@ -96,7 +96,7 @@ export default ({ getService }: FtrProviderContext): void => { { name: '7bgwxrbmcu', count: 1 }, { name: 'jf9e87gsut', count: 1 }, ]) - ); + ).to.be(true); }); }); diff --git a/x-pack/test/cases_api_integration/spaces_only/tests/common/internal/suggest_user_profiles.ts b/x-pack/test/cases_api_integration/spaces_only/tests/common/internal/suggest_user_profiles.ts index 44245f9b10e12d..c10c7a6b63997c 100644 --- a/x-pack/test/cases_api_integration/spaces_only/tests/common/internal/suggest_user_profiles.ts +++ b/x-pack/test/cases_api_integration/spaces_only/tests/common/internal/suggest_user_profiles.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { suggestUserProfiles } from '../../../../common/lib/utils'; +import { suggestUserProfiles } from '../../../../common/lib/user_profiles'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export diff --git a/x-pack/test/functional/services/cases/api.ts b/x-pack/test/functional/services/cases/api.ts index ad4678adcafc35..983ee667a2ef80 100644 --- a/x-pack/test/functional/services/cases/api.ts +++ b/x-pack/test/functional/services/cases/api.ts @@ -13,12 +13,19 @@ import { createComment, updateCase, } from '../../../cases_api_integration/common/lib/utils'; +import { + loginUsers, + suggestUserProfiles, +} from '../../../cases_api_integration/common/lib/user_profiles'; +import { User } from '../../../cases_api_integration/common/lib/authentication/types'; + import { FtrProviderContext } from '../../ftr_provider_context'; import { generateRandomCaseWithoutConnector } from './helpers'; export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { const kbnSupertest = getService('supertest'); const es = getService('es'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); return { async createCase(overwrites: Partial<CasePostRequest> = {}): Promise<CaseResponse> { @@ -76,5 +83,16 @@ export function CasesAPIServiceProvider({ getService }: FtrProviderContext) { }, }); }, + + async activateUserProfiles(users: User[]) { + await loginUsers({ + supertest: supertestWithoutAuth, + users, + }); + }, + + async suggestUserProfiles(options: Parameters<typeof suggestUserProfiles>[0]['req']) { + return suggestUserProfiles({ supertest: kbnSupertest, req: options }); + }, }; } diff --git a/x-pack/test/functional/services/cases/common.ts b/x-pack/test/functional/services/cases/common.ts index 5b854979adfc1b..8a61358d04521a 100644 --- a/x-pack/test/functional/services/cases/common.ts +++ b/x-pack/test/functional/services/cases/common.ts @@ -89,5 +89,17 @@ export function CasesCommonServiceProvider({ getService, getPageObject }: FtrPro } }); }, + + async setSearchTextInAssigneesPopover(text: string) { + await ( + await (await find.byClassName('euiContextMenuPanel')).findByClassName('euiFieldSearch') + ).type(text); + await header.waitUntilLoadingHasFinished(); + }, + + async selectFirstRowInAssigneesPopover() { + await (await find.byClassName('euiSelectableListItem__content')).click(); + await header.waitUntilLoadingHasFinished(); + }, }; } diff --git a/x-pack/test/functional/services/cases/create.ts b/x-pack/test/functional/services/cases/create.ts index e46201b1996c1e..872113f1a51be8 100644 --- a/x-pack/test/functional/services/cases/create.ts +++ b/x-pack/test/functional/services/cases/create.ts @@ -84,7 +84,7 @@ export function CasesCreateViewServiceProvider( }, async setCaseTags(tag: string) { - await comboBox.setCustom('comboBoxInput', tag); + await comboBox.setCustom('caseTags', tag); }, async assertCreateCaseFlyoutVisible(expectVisible = true) { diff --git a/x-pack/test/functional/services/cases/index.ts b/x-pack/test/functional/services/cases/index.ts index b4cfee637cb468..8ecabdac8c4c5d 100644 --- a/x-pack/test/functional/services/cases/index.ts +++ b/x-pack/test/functional/services/cases/index.ts @@ -20,7 +20,7 @@ export function CasesServiceProvider(context: FtrProviderContext) { return { api: CasesAPIServiceProvider(context), common: casesCommon, - casesTable: CasesTableServiceProvider(context), + casesTable: CasesTableServiceProvider(context, casesCommon), create: CasesCreateViewServiceProvider(context, casesCommon), navigation: CasesNavigationProvider(context), singleCase: CasesSingleViewServiceProvider(context), diff --git a/x-pack/test/functional/services/cases/list.ts b/x-pack/test/functional/services/cases/list.ts index 95b0a746db8ca4..a5f650198cf226 100644 --- a/x-pack/test/functional/services/cases/list.ts +++ b/x-pack/test/functional/services/cases/list.ts @@ -10,8 +10,12 @@ import { CaseStatuses } from '@kbn/cases-plugin/common'; import { CaseSeverityWithAll } from '@kbn/cases-plugin/common/ui'; import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { CasesCommon } from './common'; -export function CasesTableServiceProvider({ getService, getPageObject }: FtrProviderContext) { +export function CasesTableServiceProvider( + { getService, getPageObject }: FtrProviderContext, + casesCommon: CasesCommon +) { const common = getPageObject('common'); const testSubjects = getService('testSubjects'); const find = getService('find'); @@ -132,13 +136,11 @@ export function CasesTableServiceProvider({ getService, getPageObject }: FtrProv await testSubjects.click(`case-severity-filter-${severity}`); }, - async filterByReporter(reporter: string) { - await common.clickAndValidate( - 'options-filter-popover-button-Reporter', - `options-filter-popover-item-${reporter}` - ); + async filterByAssignee(assignee: string) { + await common.clickAndValidate('options-filter-popover-button-assignees', 'euiSelectableList'); - await testSubjects.click(`options-filter-popover-item-${reporter}`); + await casesCommon.setSearchTextInAssigneesPopover(assignee); + await casesCommon.selectFirstRowInAssigneesPopover(); }, async filterByOwner(owner: string) { diff --git a/x-pack/test/functional/services/cases/single_case_view.ts b/x-pack/test/functional/services/cases/single_case_view.ts index 2db687f514778d..6bdd35ee642e54 100644 --- a/x-pack/test/functional/services/cases/single_case_view.ts +++ b/x-pack/test/functional/services/cases/single_case_view.ts @@ -107,5 +107,15 @@ export function CasesSingleViewServiceProvider({ getService, getPageObject }: Ft `Expected case description to be '${expectedDescription}' (got '${actualDescription}')` ); }, + + async openAssigneesPopover() { + await common.clickAndValidate('case-view-assignees-edit-button', 'euiSelectableList'); + await header.waitUntilLoadingHasFinished(); + }, + + async closeAssigneesPopover() { + await testSubjects.click('case-refresh'); + await header.waitUntilLoadingHasFinished(); + }, }; } diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/common/users.ts b/x-pack/test/functional_with_es_ssl/apps/cases/common/users.ts index 282072dbb8dce5..8d213e5b780754 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/common/users.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/common/users.ts @@ -30,4 +30,10 @@ export const casesAllUser: User = { roles: [casesAll.name], }; -export const users = [casesReadDeleteUser, casesNoDeleteUser, casesAllUser]; +export const casesAllUser2: User = { + username: 'cases_all_user2', + password: 'password', + roles: [casesAll.name], +}; + +export const users = [casesReadDeleteUser, casesNoDeleteUser, casesAllUser, casesAllUser2]; diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts b/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts index a825bda9b90ee6..ec8e05ceb9b9d9 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/list_view.ts @@ -10,6 +10,11 @@ import { CaseStatuses } from '@kbn/cases-plugin/common'; import { CaseSeverity } from '@kbn/cases-plugin/common/api'; import { SeverityAll } from '@kbn/cases-plugin/common/ui'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { + createUsersAndRoles, + deleteUsersAndRoles, +} from '../../../cases_api_integration/common/lib/authentication'; +import { users, roles, casesAllUser, casesAllUser2 } from './common'; export default ({ getPageObject, getService }: FtrProviderContext) => { const header = getPageObject('header'); @@ -85,14 +90,20 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { const caseTitle = 'matchme'; before(async () => { + await createUsersAndRoles(getService, users, roles); + await cases.api.activateUserProfiles([casesAllUser, casesAllUser2]); + + const profiles = await cases.api.suggestUserProfiles({ name: 'all', owners: ['cases'] }); + await cases.api.createCase({ title: caseTitle, tags: ['one'], description: 'lots of information about an incident', }); await cases.api.createCase({ title: 'test2', tags: ['two'] }); - await cases.api.createCase({ title: 'test3' }); - await cases.api.createCase({ title: 'test4' }); + await cases.api.createCase({ title: 'test3', assignees: [{ uid: profiles[0].uid }] }); + await cases.api.createCase({ title: 'test4', assignees: [{ uid: profiles[1].uid }] }); + await header.waitUntilLoadingHasFinished(); await cases.casesTable.waitForCasesToBeListed(); }); @@ -108,6 +119,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { after(async () => { await cases.api.deleteAllCases(); await cases.casesTable.waitForCasesToBeDeleted(); + await deleteUsersAndRoles(getService, users, roles); }); it('filters cases from the list using a full string match', async () => { @@ -186,19 +198,20 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await cases.casesTable.validateCasesTableHasNthRows(1); }); - /** - * TODO: Improve the test by creating a case from a - * different user and filter by the new user - * and not the default one - */ - it('filters cases by reporter', async () => { - await cases.casesTable.filterByReporter('elastic'); - await cases.casesTable.validateCasesTableHasNthRows(4); + it('filters cases by the first cases all user assignee', async () => { + await cases.casesTable.filterByAssignee('all'); + await cases.casesTable.validateCasesTableHasNthRows(1); + }); + + it('filters cases by the casesAllUser2 assignee', async () => { + await cases.casesTable.filterByAssignee('2'); + await cases.casesTable.validateCasesTableHasNthRows(1); }); }); describe('severity filtering', () => { before(async () => { + await cases.navigation.navigateToApp(); await cases.api.createCase({ severity: CaseSeverity.LOW }); await cases.api.createCase({ severity: CaseSeverity.LOW }); await cases.api.createCase({ severity: CaseSeverity.HIGH }); @@ -207,6 +220,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await header.waitUntilLoadingHasFinished(); await cases.casesTable.waitForCasesToBeListed(); }); + beforeEach(async () => { /** * There is no easy way to clear the filtering. diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts b/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts index 223127125e66d9..52540169a4c8d0 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/view_case.ts @@ -10,6 +10,11 @@ import uuid from 'uuid'; import { CaseStatuses } from '@kbn/cases-plugin/common'; import { CaseSeverity } from '@kbn/cases-plugin/common/api'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { + createUsersAndRoles, + deleteUsersAndRoles, +} from '../../../cases_api_integration/common/lib/authentication'; +import { users, roles, casesAllUser } from './common'; export default ({ getPageObject, getService }: FtrProviderContext) => { const header = getPageObject('header'); @@ -18,21 +23,12 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { const cases = getService('cases'); const retry = getService('retry'); const comboBox = getService('comboBox'); + const security = getPageObject('security'); + const kibanaServer = getService('kibanaServer'); describe('View case', () => { describe('properties', () => { - // create the case to test on - before(async () => { - await cases.navigation.navigateToApp(); - await cases.api.createNthRandomCases(1); - await cases.casesTable.waitForCasesToBeListed(); - await cases.casesTable.goToFirstListedCase(); - await header.waitUntilLoadingHasFinished(); - }); - - after(async () => { - await cases.api.deleteAllCases(); - }); + createOneCaseBeforeDeleteAllAfter(getPageObject, getService); it('edits a case title from the case view page', async () => { const newTitle = `test-${uuid.v4()}`; @@ -167,18 +163,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); describe('actions', () => { - // create the case to test on - before(async () => { - await cases.navigation.navigateToApp(); - await cases.api.createNthRandomCases(1); - await cases.casesTable.waitForCasesToBeListed(); - await cases.casesTable.goToFirstListedCase(); - await header.waitUntilLoadingHasFinished(); - }); - - after(async () => { - await cases.api.deleteAllCases(); - }); + createOneCaseBeforeDeleteAllAfter(getPageObject, getService); it('deletes the case successfully', async () => { await cases.singleCase.deleteCase(); @@ -187,21 +172,12 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); describe('Severity field', () => { - before(async () => { - await cases.navigation.navigateToApp(); - await cases.api.createNthRandomCases(1); - await cases.casesTable.waitForCasesToBeListed(); - await cases.casesTable.goToFirstListedCase(); - await header.waitUntilLoadingHasFinished(); - }); - - after(async () => { - await cases.api.deleteAllCases(); - }); + createOneCaseBeforeDeleteAllAfter(getPageObject, getService); it('shows the severity field on the sidebar', async () => { await testSubjects.existOrFail('case-severity-selection'); }); + it('changes the severity level from the selector', async () => { await cases.common.selectSeverity(CaseSeverity.MEDIUM); await header.waitUntilLoadingHasFinished(); @@ -212,20 +188,128 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); }); - describe('Tabs', () => { - // create the case to test on + describe('Assignees field', () => { before(async () => { - await cases.navigation.navigateToApp(); - await cases.api.createNthRandomCases(1); - await cases.casesTable.waitForCasesToBeListed(); - await cases.casesTable.goToFirstListedCase(); - await header.waitUntilLoadingHasFinished(); + await createUsersAndRoles(getService, users, roles); + await cases.api.activateUserProfiles([casesAllUser]); }); after(async () => { - await cases.api.deleteAllCases(); + await deleteUsersAndRoles(getService, users, roles); + }); + + describe('unknown users', () => { + beforeEach(async () => { + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.5.0/cases_assignees.json' + ); + + await cases.navigation.navigateToApp(); + await cases.casesTable.waitForCasesToBeListed(); + await cases.casesTable.goToFirstListedCase(); + await header.waitUntilLoadingHasFinished(); + }); + + afterEach(async () => { + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.5.0/cases_assignees.json' + ); + + await cases.api.deleteAllCases(); + }); + + it('shows the unknown assignee', async () => { + await testSubjects.existOrFail('user-profile-assigned-user-group-abc'); + }); + + it('removes the unknown assignee when selecting the remove all users in the popover', async () => { + await testSubjects.existOrFail('user-profile-assigned-user-group-abc'); + + await cases.singleCase.openAssigneesPopover(); + await cases.common.setSearchTextInAssigneesPopover('case'); + await cases.common.selectFirstRowInAssigneesPopover(); + + await (await find.byButtonText('Remove all assignees')).click(); + await cases.singleCase.closeAssigneesPopover(); + await testSubjects.missingOrFail('user-profile-assigned-user-group-abc'); + }); + }); + + describe('login with cases all user', () => { + before(async () => { + await security.forceLogout(); + await security.login(casesAllUser.username, casesAllUser.password); + await createAndNavigateToCase(getPageObject, getService); + }); + + after(async () => { + await cases.api.deleteAllCases(); + await security.forceLogout(); + }); + + it('assigns the case to the current user when clicking the assign to self link', async () => { + await testSubjects.click('case-view-assign-yourself-link'); + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user'); + }); }); + describe('logs in with default user', () => { + createOneCaseBeforeDeleteAllAfter(getPageObject, getService); + + afterEach(async () => { + await cases.singleCase.closeAssigneesPopover(); + }); + + it('shows the assign users popover when clicked', async () => { + await testSubjects.missingOrFail('euiSelectableList'); + + await cases.singleCase.openAssigneesPopover(); + }); + + it('assigns a user from the popover', async () => { + await cases.singleCase.openAssigneesPopover(); + await cases.common.setSearchTextInAssigneesPopover('case'); + await cases.common.selectFirstRowInAssigneesPopover(); + + // navigate out of the modal + await cases.singleCase.closeAssigneesPopover(); + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user'); + }); + }); + + describe('logs in with default user and creates case before each', () => { + createOneCaseBeforeDeleteAllAfter(getPageObject, getService); + + it('removes an assigned user', async () => { + await cases.singleCase.openAssigneesPopover(); + await cases.common.setSearchTextInAssigneesPopover('case'); + await cases.common.selectFirstRowInAssigneesPopover(); + + // navigate out of the modal + await cases.singleCase.closeAssigneesPopover(); + await header.waitUntilLoadingHasFinished(); + await testSubjects.existOrFail('user-profile-assigned-user-group-cases_all_user'); + + // hover over the assigned user + await ( + await find.byCssSelector( + '[data-test-subj="user-profile-assigned-user-group-cases_all_user"]' + ) + ).moveMouseTo(); + + // delete the user + await testSubjects.click('user-profile-assigned-user-cross-cases_all_user'); + + await testSubjects.existOrFail('case-view-assign-yourself-link'); + }); + }); + }); + + describe('Tabs', () => { + createOneCaseBeforeDeleteAllAfter(getPageObject, getService); + it('shows the "activity" tab by default', async () => { await testSubjects.existOrFail('case-view-tab-title-activity'); await testSubjects.existOrFail('case-view-tab-content-activity'); @@ -239,3 +323,32 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); }); }; + +const createOneCaseBeforeDeleteAllAfter = ( + getPageObject: FtrProviderContext['getPageObject'], + getService: FtrProviderContext['getService'] +) => { + const cases = getService('cases'); + + before(async () => { + await createAndNavigateToCase(getPageObject, getService); + }); + + after(async () => { + await cases.api.deleteAllCases(); + }); +}; + +const createAndNavigateToCase = async ( + getPageObject: FtrProviderContext['getPageObject'], + getService: FtrProviderContext['getService'] +) => { + const header = getPageObject('header'); + const cases = getService('cases'); + + await cases.navigation.navigateToApp(); + await cases.api.createNthRandomCases(1); + await cases.casesTable.waitForCasesToBeListed(); + await cases.casesTable.goToFirstListedCase(); + await header.waitUntilLoadingHasFinished(); +}; diff --git a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json index 56e1f9fd62a08f..c7918341da86e5 100644 --- a/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json +++ b/x-pack/test/functional_with_es_ssl/fixtures/plugins/cases/kibana.json @@ -3,7 +3,7 @@ "owner": { "name": "Response Ops", "githubTeam": "response-ops" }, "version": "1.0.0", "kibanaVersion": "kibana", - "requiredPlugins": ["cases", "embeddable", "lens", "kibanaReact", "esUiShared"], + "requiredPlugins": ["cases", "embeddable", "lens", "kibanaReact", "esUiShared", "security"], "server": true, "ui": true } From 9f0a9e73f2b15791bf92c072f27a3a125aca6db5 Mon Sep 17 00:00:00 2001 From: Faisal Kanout <faisal.kanout@elastic.co> Date: Mon, 12 Sep 2022 13:37:35 +0200 Subject: [PATCH 055/144] [ResponseOps][ActionableObservability] - Add unit tests for Rule Alerts Summary components (#138635) * Add data obj test and the first test with needed mocks * WIP * Add tests * Add hook test (error handling) * Add hook tests * Update test name * extract mock in a separate folder * Add a new test to check the query sent to ES * Move mocks to the mock folder * Update mockChartData function * Fix test --- .../use_load_rule_alerts_aggregations.test.ts | 67 +++ .../use_load_rule_alerts_aggregations.ts | 2 +- .../mock/rule_details/alert_summary/index.ts | 445 ++++++++++++++++++ .../rule_alerts_summary.test.tsx | 253 ++++++++++ .../alert_summary/rule_alerts_summary.tsx | 9 +- 5 files changed, 771 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.test.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/mock/rule_details/alert_summary/index.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.test.tsx diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.test.ts new file mode 100644 index 00000000000000..293c1e992ac18e --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.test.ts @@ -0,0 +1,67 @@ +/* + * 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 { ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common'; +import { renderHook } from '@testing-library/react-hooks'; +import { useKibana } from '../../common/lib/kibana'; +import { mockAggsResponse, mockChartData } from '../mock/rule_details/alert_summary'; +import { useLoadRuleAlertsAggs } from './use_load_rule_alerts_aggregations'; + +jest.mock('../../common/lib/kibana'); + +const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>; +describe('useLoadRuleAlertsAggs', () => { + beforeEach(() => { + jest.clearAllMocks(); + useKibanaMock().services.http.post = jest.fn().mockResolvedValue({ ...mockAggsResponse() }); + useKibanaMock().services.http.get = jest.fn().mockResolvedValue({ index_name: ['mock_index'] }); + }); + + it('should return the expected chart data from the Elasticsearch Aggs. query', async () => { + const { result, waitForNextUpdate } = renderHook(() => + useLoadRuleAlertsAggs({ + features: ALERTS_FEATURE_ID, + ruleId: 'c95bc120-1d56-11ed-9cc7-e7214ada1128', + }) + ); + expect(result.current).toEqual({ + isLoadingRuleAlertsAggs: true, + ruleAlertsAggs: { active: 0, recovered: 0 }, + alertsChartData: [], + }); + + await waitForNextUpdate(); + const { ruleAlertsAggs, errorRuleAlertsAggs, alertsChartData } = result.current; + expect(ruleAlertsAggs).toEqual({ + active: 1, + recovered: 7, + }); + expect(alertsChartData).toEqual(mockChartData()); + expect(errorRuleAlertsAggs).toBeFalsy(); + expect(alertsChartData.length).toEqual(33); + }); + + it('should have the correct query body sent to Elasticsearch', async () => { + const ruleId = 'c95bc120-1d56-11ed-9cc7-e7214ada1128'; + const { waitForNextUpdate } = renderHook(() => + useLoadRuleAlertsAggs({ + features: ALERTS_FEATURE_ID, + ruleId, + }) + ); + + await waitForNextUpdate(); + const body = `{"index":"mock_index","size":0,"query":{"bool":{"must":[{"term":{"kibana.alert.rule.uuid":"${ruleId}"}},{"range":{"@timestamp":{"gte":"now-30d","lt":"now"}}},{"bool":{"should":[{"term":{"kibana.alert.status":"active"}},{"term":{"kibana.alert.status":"recovered"}}]}}]}},"aggs":{"total":{"filters":{"filters":{"totalActiveAlerts":{"term":{"kibana.alert.status":"active"}},"totalRecoveredAlerts":{"term":{"kibana.alert.status":"recovered"}}}}},"statusPerDay":{"date_histogram":{"field":"@timestamp","fixed_interval":"1d","extended_bounds":{"min":"now-30d","max":"now"}},"aggs":{"alertStatus":{"terms":{"field":"kibana.alert.status"}}}}}}`; + + expect(useKibanaMock().services.http.post).toHaveBeenCalledWith( + '/internal/rac/alerts/find', + expect.objectContaining({ + body, + }) + ); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.ts index aeba9605cb9a6a..c938b0b2cc13f6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_alerts_aggregations.ts @@ -78,7 +78,7 @@ export function useLoadRuleAlertsAggs({ features, ruleId }: UseLoadRuleAlertsAgg setRuleAlertsAggs((oldState: LoadRuleAlertsAggs) => ({ ...oldState, isLoadingRuleAlertsAggs: false, - errorRuleAlertsAggs: 'error', + errorRuleAlertsAggs: error, alertsChartData: [], })); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/mock/rule_details/alert_summary/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/mock/rule_details/alert_summary/index.ts new file mode 100644 index 00000000000000..b0e5416bbf63db --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/mock/rule_details/alert_summary/index.ts @@ -0,0 +1,445 @@ +/* + * 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 { Rule } from '../../../../types'; +import { AlertChartData } from '../../../sections/rule_details/components/alert_summary'; + +export const mockRule = (): Rule => { + return { + id: '1', + name: 'test rule', + tags: ['tag1'], + enabled: true, + ruleTypeId: 'test_rule_type', + schedule: { interval: '1s' }, + actions: [], + params: { name: 'test rule type name' }, + createdBy: null, + updatedBy: null, + apiKeyOwner: null, + throttle: '1m', + muteAll: false, + mutedInstanceIds: [], + createdAt: new Date(), + updatedAt: new Date(), + consumer: 'alerts', + notifyWhen: 'onActiveAlert', + executionStatus: { + status: 'active', + lastDuration: 500, + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + }, + monitoring: { + execution: { + history: [ + { + success: true, + duration: 1000000, + timestamp: 1234567, + }, + { + success: true, + duration: 200000, + timestamp: 1234567, + }, + { + success: false, + duration: 300000, + timestamp: 1234567, + }, + ], + calculated_metrics: { + success_ratio: 0.66, + p50: 200000, + p95: 300000, + p99: 300000, + }, + }, + }, + }; +}; + +export function mockChartData(): AlertChartData[] { + return [ + { + date: 1660608000000, + count: 6, + status: 'recovered', + }, + { + date: 1660694400000, + count: 1, + status: 'recovered', + }, + { + date: 1660694400000, + count: 1, + status: 'active', + }, + { + date: 1658102400000, + count: 6, + status: 'total', + }, + { + date: 1658188800000, + count: 6, + status: 'total', + }, + { + date: 1658275200000, + count: 6, + status: 'total', + }, + { + date: 1658361600000, + count: 6, + status: 'total', + }, + { + date: 1658448000000, + count: 6, + status: 'total', + }, + { + date: 1658534400000, + count: 6, + status: 'total', + }, + { + date: 1658620800000, + count: 6, + status: 'total', + }, + { + date: 1658707200000, + count: 6, + status: 'total', + }, + { + date: 1658793600000, + count: 6, + status: 'total', + }, + { + date: 1658880000000, + count: 6, + status: 'total', + }, + { + date: 1658966400000, + count: 6, + status: 'total', + }, + { + date: 1659052800000, + count: 6, + status: 'total', + }, + { + date: 1659139200000, + count: 6, + status: 'total', + }, + { + date: 1659225600000, + count: 6, + status: 'total', + }, + { + date: 1659312000000, + count: 6, + status: 'total', + }, + { + date: 1659398400000, + count: 6, + status: 'total', + }, + { + date: 1659484800000, + count: 6, + status: 'total', + }, + { + date: 1659571200000, + count: 6, + status: 'total', + }, + { + date: 1659657600000, + count: 6, + status: 'total', + }, + { + date: 1659744000000, + count: 6, + status: 'total', + }, + { + date: 1659830400000, + count: 6, + status: 'total', + }, + { + date: 1659916800000, + count: 6, + status: 'total', + }, + { + date: 1660003200000, + count: 6, + status: 'total', + }, + { + date: 1660089600000, + count: 6, + status: 'total', + }, + { + date: 1660176000000, + count: 6, + status: 'total', + }, + { + date: 1660262400000, + count: 6, + status: 'total', + }, + { + date: 1660348800000, + count: 6, + status: 'total', + }, + { + date: 1660435200000, + count: 6, + status: 'total', + }, + { + date: 1660521600000, + count: 6, + status: 'total', + }, + { + date: 1660694400000, + count: 4, + status: 'total', + }, + ]; +} + +export const mockAggsResponse = () => { + return { + aggregations: { + total: { + buckets: { totalActiveAlerts: { doc_count: 1 }, totalRecoveredAlerts: { doc_count: 7 } }, + }, + statusPerDay: { + buckets: [ + { + key_as_string: '2022-07-18T00:00:00.000Z', + key: 1658102400000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-19T00:00:00.000Z', + key: 1658188800000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-20T00:00:00.000Z', + key: 1658275200000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-21T00:00:00.000Z', + key: 1658361600000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-22T00:00:00.000Z', + key: 1658448000000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-23T00:00:00.000Z', + key: 1658534400000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-24T00:00:00.000Z', + key: 1658620800000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-25T00:00:00.000Z', + key: 1658707200000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-26T00:00:00.000Z', + key: 1658793600000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-27T00:00:00.000Z', + key: 1658880000000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-28T00:00:00.000Z', + key: 1658966400000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-29T00:00:00.000Z', + key: 1659052800000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-30T00:00:00.000Z', + key: 1659139200000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-07-31T00:00:00.000Z', + key: 1659225600000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-01T00:00:00.000Z', + key: 1659312000000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-02T00:00:00.000Z', + key: 1659398400000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-03T00:00:00.000Z', + key: 1659484800000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-04T00:00:00.000Z', + key: 1659571200000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-05T00:00:00.000Z', + key: 1659657600000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-06T00:00:00.000Z', + key: 1659744000000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-07T00:00:00.000Z', + key: 1659830400000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-08T00:00:00.000Z', + key: 1659916800000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-09T00:00:00.000Z', + key: 1660003200000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-10T00:00:00.000Z', + key: 1660089600000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-11T00:00:00.000Z', + key: 1660176000000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-12T00:00:00.000Z', + key: 1660262400000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-13T00:00:00.000Z', + key: 1660348800000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-14T00:00:00.000Z', + key: 1660435200000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-15T00:00:00.000Z', + key: 1660521600000, + doc_count: 0, + alertStatus: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, + }, + { + key_as_string: '2022-08-16T00:00:00.000Z', + key: 1660608000000, + doc_count: 6, + alertStatus: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ key: 'recovered', doc_count: 6 }], + }, + }, + { + key_as_string: '2022-08-17T00:00:00.000Z', + key: 1660694400000, + doc_count: 2, + alertStatus: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { key: 'active', doc_count: 1 }, + { key: 'recovered', doc_count: 1 }, + ], + }, + }, + ], + }, + }, + }; +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.test.tsx new file mode 100644 index 00000000000000..39264020f30a38 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.test.tsx @@ -0,0 +1,253 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { nextTick } from '@kbn/test-jest-helpers'; +import { RuleAlertsSummary } from './rule_alerts_summary'; +import { mount, ReactWrapper } from 'enzyme'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common'; +import { mockRule } from '../../../../mock/rule_details/alert_summary'; +import { AlertChartData } from './types'; + +jest.mock('@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting', () => ({ + useUiSetting: jest.fn().mockImplementation(() => true), +})); + +jest.mock('../../../../hooks/use_load_rule_types', () => ({ + useLoadRuleTypes: jest.fn(), +})); + +jest.mock('../../../../hooks/use_load_rule_alerts_aggregations', () => ({ + useLoadRuleAlertsAggs: jest.fn().mockReturnValue({ + ruleAlertsAggs: { active: 1, recovered: 7 }, + alertsChartData: mockChartData(), + }), +})); + +const { useLoadRuleTypes } = jest.requireMock('../../../../hooks/use_load_rule_types'); +const ruleTypes = [ + { + id: 'test_rule_type', + name: 'some rule type', + actionGroups: [{ id: 'default', name: 'Default' }], + recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, + actionVariables: { context: [], state: [] }, + defaultActionGroupId: 'default', + producer: ALERTS_FEATURE_ID, + minimumLicenseRequired: 'basic', + enabledInLicense: true, + authorizedConsumers: { + [ALERTS_FEATURE_ID]: { read: true, all: false }, + }, + ruleTaskTimeout: '1m', + }, +]; + +describe('Rule Alert Summary', () => { + let wrapper: ReactWrapper; + + async function setup() { + const mockedRule = mockRule(); + + useLoadRuleTypes.mockReturnValue({ ruleTypes }); + + wrapper = mount( + <IntlProvider locale="en"> + <RuleAlertsSummary + rule={mockedRule} + filteredRuleTypes={['apm', 'uptime', 'metric', 'logs']} + /> + </IntlProvider> + ); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + } + beforeAll(async () => setup()); + it('should render the Rule Alerts Summary component', async () => { + expect(wrapper.find('[data-test-subj="ruleAlertsSummary"]')).toBeTruthy(); + }); + + it('should show zeros for all alerts counters', async () => { + expect(wrapper.find('[data-test-subj="activeAlertsCount"]').text()).toEqual('1'); + expect(wrapper.find('[data-test-subj="recoveredAlertsCount"]').text()).toBe('7'); + expect(wrapper.find('[data-test-subj="totalAlertsCount"]').text()).toBe('8'); + }); +}); + +// This function should stay in the same file as the test otherwise the test will fail. +function mockChartData(): AlertChartData[] { + return [ + { + date: 1660608000000, + count: 6, + status: 'recovered', + }, + { + date: 1660694400000, + count: 1, + status: 'recovered', + }, + { + date: 1660694400000, + count: 1, + status: 'active', + }, + { + date: 1658102400000, + count: 6, + status: 'total', + }, + { + date: 1658188800000, + count: 6, + status: 'total', + }, + { + date: 1658275200000, + count: 6, + status: 'total', + }, + { + date: 1658361600000, + count: 6, + status: 'total', + }, + { + date: 1658448000000, + count: 6, + status: 'total', + }, + { + date: 1658534400000, + count: 6, + status: 'total', + }, + { + date: 1658620800000, + count: 6, + status: 'total', + }, + { + date: 1658707200000, + count: 6, + status: 'total', + }, + { + date: 1658793600000, + count: 6, + status: 'total', + }, + { + date: 1658880000000, + count: 6, + status: 'total', + }, + { + date: 1658966400000, + count: 6, + status: 'total', + }, + { + date: 1659052800000, + count: 6, + status: 'total', + }, + { + date: 1659139200000, + count: 6, + status: 'total', + }, + { + date: 1659225600000, + count: 6, + status: 'total', + }, + { + date: 1659312000000, + count: 6, + status: 'total', + }, + { + date: 1659398400000, + count: 6, + status: 'total', + }, + { + date: 1659484800000, + count: 6, + status: 'total', + }, + { + date: 1659571200000, + count: 6, + status: 'total', + }, + { + date: 1659657600000, + count: 6, + status: 'total', + }, + { + date: 1659744000000, + count: 6, + status: 'total', + }, + { + date: 1659830400000, + count: 6, + status: 'total', + }, + { + date: 1659916800000, + count: 6, + status: 'total', + }, + { + date: 1660003200000, + count: 6, + status: 'total', + }, + { + date: 1660089600000, + count: 6, + status: 'total', + }, + { + date: 1660176000000, + count: 6, + status: 'total', + }, + { + date: 1660262400000, + count: 6, + status: 'total', + }, + { + date: 1660348800000, + count: 6, + status: 'total', + }, + { + date: 1660435200000, + count: 6, + status: 'total', + }, + { + date: 1660521600000, + count: 6, + status: 'total', + }, + { + date: 1660694400000, + count: 4, + status: 'total', + }, + ]; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.tsx index 6fc657d051594f..708b12ceb7b4ae 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/alert_summary/rule_alerts_summary.tsx @@ -98,6 +98,7 @@ export const RuleAlertsSummary = ({ rule, filteredRuleTypes }: RuleAlertsSummary if (errorRuleAlertsAggs) return ( <EuiEmptyPrompt + data-test-subj="alertsRuleSummaryErrorPrompt" iconType="alert" color="danger" title={ @@ -123,7 +124,7 @@ export const RuleAlertsSummary = ({ rule, filteredRuleTypes }: RuleAlertsSummary ); const isVisibleFunction: FilterPredicate = (series) => series.splitAccessors.get('g') !== 'total'; return ( - <EuiPanel hasShadow={false} hasBorder> + <EuiPanel data-test-subj="ruleAlertsSummary" hasShadow={false} hasBorder> <EuiFlexGroup direction="column"> <EuiFlexItem grow={false}> <EuiFlexGroup direction="column"> @@ -156,7 +157,7 @@ export const RuleAlertsSummary = ({ rule, filteredRuleTypes }: RuleAlertsSummary /> </EuiText> <EuiText> - <h4>{active + recovered}</h4> + <h4 data-test-subj="totalAlertsCount">{active + recovered}</h4> </EuiText> </EuiFlexItem> </EuiFlexGroup> @@ -169,7 +170,7 @@ export const RuleAlertsSummary = ({ rule, filteredRuleTypes }: RuleAlertsSummary /> </EuiText> <EuiText color={LIGHT_THEME.colors.vizColors[2]}> - <h4>{active}</h4> + <h4 data-test-subj="activeAlertsCount">{active}</h4> </EuiText> </EuiFlexItem> </EuiFlexGroup> @@ -183,7 +184,7 @@ export const RuleAlertsSummary = ({ rule, filteredRuleTypes }: RuleAlertsSummary </EuiText> <EuiFlexItem> <EuiText color={LIGHT_THEME.colors.vizColors[1]}> - <h4>{recovered}</h4> + <h4 data-test-subj="recoveredAlertsCount">{recovered}</h4> </EuiText> </EuiFlexItem> </EuiFlexItem> From 5a0313b241aa2a9b1e79f22eccedfdf11b96c2c9 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi <maryam.saeidi@elastic.co> Date: Mon, 12 Sep 2022 14:31:00 +0200 Subject: [PATCH 056/144] [Actionable Observability] Integrate the shareable alert table in the Overview Page (#140024) * Refactor observability overview page * Fix type and file name * Use shareable alert table in overview page * Add functional test for overview page * Fix functional tests * Fix flaky test * Remove only and add retry for opening alerts section * Wait for the overview page to load before opening alerts section * Add waitForAlertsSectionToAppear * Add waiting for alerts table loading to disappear * Add longer timeout for loading alerts table * Increase timeout for alerts table to be loaded --- .../public/components/app/section/index.tsx | 1 + .../containers/alerts_page/alerts_page.tsx | 18 ++-- .../containers/alerts_page/constants.ts | 3 +- .../containers/overview_page/constants.ts | 1 + .../overview_page/overview_page.tsx | 43 +++++---- .../__snapshots__/build_es_query.test.ts.snap | 21 +++++ .../build_es_query}/build_es_query.test.ts | 3 + .../build_es_query}/build_es_query.ts | 5 +- .../helpers => utils/build_es_query}/index.ts | 0 .../services/observability/index.ts | 3 + .../services/observability/overview/common.ts | 89 +++++++++++++++++++ .../services/observability/overview/index.ts | 18 ++++ .../apps/observability/index.ts | 3 +- .../observability/pages/alerts/rule_stats.ts | 2 +- .../observability/pages/cases/case_details.ts | 3 +- .../pages/overview/alert_table.ts | 60 +++++++++++++ .../observability/pages/rule_details_page.ts | 2 +- .../apps/observability/pages/rules_page.ts | 2 + 18 files changed, 245 insertions(+), 32 deletions(-) rename x-pack/plugins/observability/public/{pages/alerts/containers/alerts_page/helpers => utils/build_es_query}/__snapshots__/build_es_query.test.ts.snap (88%) rename x-pack/plugins/observability/public/{pages/alerts/containers/alerts_page/helpers => utils/build_es_query}/build_es_query.test.ts (95%) rename x-pack/plugins/observability/public/{pages/alerts/containers/alerts_page/helpers => utils/build_es_query}/build_es_query.ts (74%) rename x-pack/plugins/observability/public/{pages/alerts/containers/alerts_page/helpers => utils/build_es_query}/index.ts (100%) create mode 100644 x-pack/test/functional/services/observability/overview/common.ts create mode 100644 x-pack/test/functional/services/observability/overview/index.ts create mode 100644 x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts diff --git a/x-pack/plugins/observability/public/components/app/section/index.tsx b/x-pack/plugins/observability/public/components/app/section/index.tsx index dae85d07685aed..149e386085d20b 100644 --- a/x-pack/plugins/observability/public/components/app/section/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/index.tsx @@ -49,6 +49,7 @@ export function SectionContainer({ initialIsOpen={initialIsOpen} id={title} buttonContentClassName="accordion-button" + data-test-subj={`accordion-${title}`} buttonContent={ <> <EuiFlexGroup gutterSize="s" alignItems="center" responsive={false}> diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx index 6ec620f535db75..974164265b50b0 100644 --- a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/alerts_page.tsx @@ -14,7 +14,6 @@ import useAsync from 'react-use/lib/useAsync'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; import { AlertConsumers, AlertStatus } from '@kbn/rule-data-utils'; -import { buildEsQuery } from './helpers'; import { AlertStatusFilterButton } from '../../../../../common/typings'; import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions'; import { observabilityFeatureId } from '../../../../../common'; @@ -23,6 +22,7 @@ import { useAlertIndexNames } from '../../../../hooks/use_alert_index_names'; import { useHasData } from '../../../../hooks/use_has_data'; import { usePluginContext } from '../../../../hooks/use_plugin_context'; import { getNoDataConfig } from '../../../../utils/no_data_config'; +import { buildEsQuery } from '../../../../utils/build_es_query'; import { LoadingObservability } from '../../../overview'; import { Provider, @@ -35,6 +35,7 @@ import { renderRuleStats } from '../../components/rule_stats'; import { ObservabilityAppServices } from '../../../../application/types'; import { ALERT_STATUS_REGEX, + ALERTS_PER_PAGE, ALERTS_TABLE_ID, BASE_ALERT_REGEX, NO_INDEX_PATTERNS, @@ -144,11 +145,6 @@ function AlertsPage() { ]; }, [indexNames]); - const timeRange = { - to: rangeTo, - from: rangeFrom, - }; - const onRefresh = () => { setRefreshNow(new Date().getTime()); }; @@ -264,9 +260,15 @@ function AlertsPage() { AlertConsumers.LOGS, AlertConsumers.UPTIME, ]} - query={buildEsQuery(timeRange, kuery)} + query={buildEsQuery( + { + to: rangeTo, + from: rangeFrom, + }, + kuery + )} showExpandToDetails={false} - pageSize={50} + pageSize={ALERTS_PER_PAGE} refreshNow={refreshNow} /> </CasesContext> diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/constants.ts b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/constants.ts index 8630c7850298b7..83b059b04f5e35 100644 --- a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/constants.ts +++ b/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/constants.ts @@ -9,7 +9,8 @@ import { DataViewBase } from '@kbn/es-query'; import { ALERT_STATUS } from '@kbn/rule-data-utils'; export const ALERTS_PAGE_ID = 'alerts-o11y'; -export const ALERTS_TABLE_ID = 'xpack.observability.alerts.table'; +export const ALERTS_PER_PAGE = 50; +export const ALERTS_TABLE_ID = 'xpack.observability.alerts.alert.table'; const regExpEscape = (str: string) => str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); export const NO_INDEX_PATTERNS: DataViewBase[] = []; diff --git a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/constants.ts b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/constants.ts index b9036ea4320af2..cca2bb765e7192 100644 --- a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/constants.ts +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/constants.ts @@ -7,5 +7,6 @@ export const CAPABILITIES_KEYS = ['logs', 'infrastructure', 'apm', 'uptime']; +export const ALERTS_TABLE_ID = 'xpack.observability.overview.alert.table'; export const ALERT_TABLE_STATE_STORAGE_KEY = 'xpack.observability.overview.alert.tableState'; export const ALERTS_PER_PAGE = 10; diff --git a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx index 5a1dfdaa302526..1f09cfc38cf4ca 100644 --- a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/overview_page.tsx @@ -4,12 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiFlyout, + EuiFlyoutSize, EuiFlyoutBody, EuiFlyoutHeader, EuiHorizontalRule, @@ -21,7 +23,7 @@ import { import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { AlertConsumers } from '@kbn/rule-data-utils'; import React, { useMemo, useRef, useCallback, useState, useEffect } from 'react'; import { calculateBucketSize } from './helpers'; @@ -38,10 +40,9 @@ import { useBreadcrumbs } from '../../../../hooks/use_breadcrumbs'; import { useFetcher } from '../../../../hooks/use_fetcher'; import { useHasData } from '../../../../hooks/use_has_data'; import { usePluginContext } from '../../../../hooks/use_plugin_context'; -import { useAlertIndexNames } from '../../../../hooks/use_alert_index_names'; +import { buildEsQuery } from '../../../../utils/build_es_query'; import { getNewsFeed } from '../../../../services/get_news_feed'; import { DataSections, LoadingObservability } from '../../components'; -import { AlertsTableTGrid } from '../../../alerts/containers/alerts_table_t_grid/alerts_table_t_grid'; import { SectionContainer } from '../../../../components/app/section'; import { ObservabilityAppServices } from '../../../../application/types'; import { useGetUserCasesPermissions } from '../../../../hooks/use_get_user_cases_permissions'; @@ -51,7 +52,7 @@ import { ObservabilityStatusProgress } from '../../../../components/app/observab import { ObservabilityStatus } from '../../../../components/app/observability_status'; import { useGuidedSetupProgress } from '../../../../hooks/use_guided_setup_progress'; import { useObservabilityTourContext } from '../../../../components/shared/tour'; -import { CAPABILITIES_KEYS, ALERT_TABLE_STATE_STORAGE_KEY, ALERTS_PER_PAGE } from './constants'; +import { CAPABILITIES_KEYS, ALERTS_PER_PAGE, ALERTS_TABLE_ID } from './constants'; export function OverviewPage() { const trackMetric = useUiTracker({ app: 'observability-overview' }); @@ -65,12 +66,13 @@ export function OverviewPage() { }, ]); const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); + const [refreshNow, setRefreshNow] = useState<number>(); - const indexNames = useAlertIndexNames(); const { cases, http, application: { capabilities }, + triggersActionsUi: { alertsTableConfigurationRegistry, getAlertsStateTable: AlertsStateTable }, } = useKibana<ObservabilityAppServices>().services; const { ObservabilityPageTemplate } = usePluginContext(); @@ -94,10 +96,6 @@ export function OverviewPage() { [absoluteStart, absoluteEnd] ); - const setRefetch = useCallback((ref) => { - refetch.current = ref; - }, []); - const handleGuidedSetupClick = useCallback(() => { if (isGuidedSetupProgressDismissed) { trackMetric({ metric: 'guided_setup_view_details_after_dismiss' }); @@ -107,6 +105,7 @@ export function OverviewPage() { }, [trackMetric, isGuidedSetupProgressDismissed, hideGuidedSetupTour]); const onTimeRangeRefresh = useCallback(() => { + setRefreshNow(new Date().getTime()); return refetch.current && refetch.current(); }, []); @@ -173,14 +172,24 @@ export function OverviewPage() { permissions={userCasesPermissions} features={{ alerts: { sync: false } }} > - <AlertsTableTGrid - setRefetch={setRefetch} - rangeFrom={relativeStart} - rangeTo={relativeEnd} - indexNames={indexNames} - itemsPerPage={ALERTS_PER_PAGE} - stateStorageKey={ALERT_TABLE_STATE_STORAGE_KEY} - storage={new Storage(window.localStorage)} + <AlertsStateTable + alertsTableConfigurationRegistry={alertsTableConfigurationRegistry} + configurationId={AlertConsumers.OBSERVABILITY} + id={ALERTS_TABLE_ID} + flyoutSize={'s' as EuiFlyoutSize} + featureIds={[ + AlertConsumers.APM, + AlertConsumers.INFRASTRUCTURE, + AlertConsumers.LOGS, + AlertConsumers.UPTIME, + ]} + query={buildEsQuery({ + from: relativeStart, + to: relativeEnd, + })} + showExpandToDetails={false} + pageSize={ALERTS_PER_PAGE} + refreshNow={refreshNow} /> </CasesContext> </SectionContainer> diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/__snapshots__/build_es_query.test.ts.snap b/x-pack/plugins/observability/public/utils/build_es_query/__snapshots__/build_es_query.test.ts.snap similarity index 88% rename from x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/__snapshots__/build_es_query.test.ts.snap rename to x-pack/plugins/observability/public/utils/build_es_query/__snapshots__/build_es_query.test.ts.snap index f52b61794ce516..fcadce3f18b19c 100644 --- a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/__snapshots__/build_es_query.test.ts.snap +++ b/x-pack/plugins/observability/public/utils/build_es_query/__snapshots__/build_es_query.test.ts.snap @@ -145,3 +145,24 @@ Object { }, } `; + +exports[`buildEsQuery should generate correct es query for {"timeRange":{"from":"2022-08-30T15:23:23.721Z","to":"2022-08-30T15:38:28.171Z"}} 1`] = ` +Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "format": "strict_date_optional_time", + "gte": "2022-08-30T15:23:23.721Z", + "lte": "2022-08-30T15:38:28.171Z", + }, + }, + }, + ], + "must": Array [], + "must_not": Array [], + "should": Array [], + }, +} +`; diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/build_es_query.test.ts b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.test.ts similarity index 95% rename from x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/build_es_query.test.ts rename to x-pack/plugins/observability/public/utils/build_es_query/build_es_query.test.ts index ad303966d046b5..4bbacaa7bb1ad3 100644 --- a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/build_es_query.test.ts +++ b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.test.ts @@ -19,6 +19,9 @@ describe('buildEsQuery', () => { timeRange: defaultTimeRange, kuery: '', }, + { + timeRange: defaultTimeRange, + }, { timeRange: defaultTimeRange, kuery: 'nestedField: { child: "something" }', diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/build_es_query.ts b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.ts similarity index 74% rename from x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/build_es_query.ts rename to x-pack/plugins/observability/public/utils/build_es_query/build_es_query.ts index a6acbb0d2e40e2..28e2942c1f6069 100644 --- a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/build_es_query.ts +++ b/x-pack/plugins/observability/public/utils/build_es_query/build_es_query.ts @@ -9,13 +9,14 @@ import { buildEsQuery as kbnBuildEsQuery, TimeRange } from '@kbn/es-query'; import { TIMESTAMP } from '@kbn/rule-data-utils'; import { getTime } from '@kbn/data-plugin/common'; -export function buildEsQuery(timeRange: TimeRange, kuery: string) { +export function buildEsQuery(timeRange: TimeRange, kuery?: string) { const timeFilter = timeRange && getTime(undefined, timeRange, { fieldName: TIMESTAMP, }); const filtersToUse = [...(timeFilter ? [timeFilter] : [])]; + const queryToUse = kuery ? { query: kuery, language: 'kuery' } : []; - return kbnBuildEsQuery(undefined, { query: kuery, language: 'kuery' }, filtersToUse); + return kbnBuildEsQuery(undefined, queryToUse, filtersToUse); } diff --git a/x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/index.ts b/x-pack/plugins/observability/public/utils/build_es_query/index.ts similarity index 100% rename from x-pack/plugins/observability/public/pages/alerts/containers/alerts_page/helpers/index.ts rename to x-pack/plugins/observability/public/utils/build_es_query/index.ts diff --git a/x-pack/test/functional/services/observability/index.ts b/x-pack/test/functional/services/observability/index.ts index 8990641cb524b1..2b2c82c4f3728c 100644 --- a/x-pack/test/functional/services/observability/index.ts +++ b/x-pack/test/functional/services/observability/index.ts @@ -8,13 +8,16 @@ import { FtrProviderContext } from '../../ftr_provider_context'; import { ObservabilityUsersProvider } from './users'; import { ObservabilityAlertsProvider } from './alerts'; +import { ObservabilityOverviewProvider } from './overview'; export function ObservabilityProvider(context: FtrProviderContext) { const alerts = ObservabilityAlertsProvider(context); const users = ObservabilityUsersProvider(context); + const overview = ObservabilityOverviewProvider(context); return { alerts, users, + overview, }; } diff --git a/x-pack/test/functional/services/observability/overview/common.ts b/x-pack/test/functional/services/observability/overview/common.ts new file mode 100644 index 00000000000000..e26e23e1e82db6 --- /dev/null +++ b/x-pack/test/functional/services/observability/overview/common.ts @@ -0,0 +1,89 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +// Based on the x-pack/test/functional/es_archives/observability/alerts archive. +const DATE_WITH_DATA = { + rangeFrom: '2021-10-18T13:36:22.109Z', + rangeTo: '2021-10-20T13:36:22.109Z', +}; + +const ALERTS_TITLE = 'Alerts'; +const ALERTS_ACCORDION_SELECTOR = `accordion-${ALERTS_TITLE}`; +const ALERTS_SECTION_BUTTON_SELECTOR = `button[aria-controls="${ALERTS_TITLE}"]`; +const ALERTS_TABLE_NO_DATA_SELECTOR = 'alertsStateTableEmptyState'; +const ALERTS_TABLE_WITH_DATA_SELECTOR = 'alertsTable'; +const ALERTS_TABLE_LOADING_SELECTOR = 'internalAlertsPageLoading'; + +export function ObservabilityOverviewCommonProvider({ + getPageObjects, + getService, +}: FtrProviderContext) { + const find = getService('find'); + const pageObjects = getPageObjects(['common']); + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + const navigateToOverviewPageWithAlerts = async () => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/overview', + `?rangeFrom=${DATE_WITH_DATA.rangeFrom}&rangeTo=${DATE_WITH_DATA.rangeTo}`, + { ensureCurrentUrl: false } + ); + }; + + const navigateToOverviewPage = async () => { + return await pageObjects.common.navigateToUrlWithBrowserHistory( + 'observability', + '/overview', + undefined, + { ensureCurrentUrl: false } + ); + }; + + const waitForAlertsAccordionToAppear = async () => { + await retry.waitFor('alert accordion to appear', async () => { + return await testSubjects.exists(ALERTS_ACCORDION_SELECTOR); + }); + }; + + const waitForAlertsTableLoadingToDisappear = async () => { + await retry.try(async () => { + await testSubjects.missingOrFail(ALERTS_TABLE_LOADING_SELECTOR, { timeout: 10000 }); + }); + }; + + const openAlertsSection = async () => { + await waitForAlertsAccordionToAppear(); + const alertSectionButton = await find.byCssSelector(ALERTS_SECTION_BUTTON_SELECTOR); + return await alertSectionButton.click(); + }; + + const openAlertsSectionAndWaitToAppear = async () => { + await openAlertsSection(); + await waitForAlertsTableLoadingToDisappear(); + await retry.waitFor('alerts table to appear', async () => { + return ( + (await testSubjects.exists(ALERTS_TABLE_NO_DATA_SELECTOR)) || + (await testSubjects.exists(ALERTS_TABLE_WITH_DATA_SELECTOR)) + ); + }); + }; + + const getAlertsTableNoDataOrFail = async () => { + return await testSubjects.existOrFail(ALERTS_TABLE_NO_DATA_SELECTOR); + }; + + return { + getAlertsTableNoDataOrFail, + navigateToOverviewPageWithAlerts, + navigateToOverviewPage, + openAlertsSectionAndWaitToAppear, + }; +} diff --git a/x-pack/test/functional/services/observability/overview/index.ts b/x-pack/test/functional/services/observability/overview/index.ts new file mode 100644 index 00000000000000..5c34d4afce99e8 --- /dev/null +++ b/x-pack/test/functional/services/observability/overview/index.ts @@ -0,0 +1,18 @@ +/* + * 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 { ObservabilityOverviewCommonProvider } from './common'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export function ObservabilityOverviewProvider(context: FtrProviderContext) { + const common = ObservabilityOverviewCommonProvider(context); + + return { + common, + }; +} diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index b3acbf5f51a8a9..e797d6812ed8d7 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -10,13 +10,14 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('ObservabilityApp', function () { loadTestFile(require.resolve('./pages/alerts')); - loadTestFile(require.resolve('./pages/cases/case_details')); loadTestFile(require.resolve('./pages/alerts/add_to_case')); loadTestFile(require.resolve('./pages/alerts/alert_status')); loadTestFile(require.resolve('./pages/alerts/pagination')); loadTestFile(require.resolve('./pages/alerts/rule_stats')); loadTestFile(require.resolve('./pages/alerts/state_synchronization')); loadTestFile(require.resolve('./pages/alerts/table_storage')); + loadTestFile(require.resolve('./pages/cases/case_details')); + loadTestFile(require.resolve('./pages/overview/alert_table')); loadTestFile(require.resolve('./exploratory_view')); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./pages/rules_page')); diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts b/x-pack/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts index 443e0616cabe24..15c960c16f7495 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/alerts/rule_stats.ts @@ -30,7 +30,7 @@ export default ({ getService }: FtrProviderContext) => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); const setup = async () => { await observability.alerts.common.setKibanaTimeZoneToUTC(); - await observability.alerts.common.navigateToTimeWithData(); + await observability.alerts.common.navigateWithoutFilter(); }; await setup(); }); diff --git a/x-pack/test/observability_functional/apps/observability/pages/cases/case_details.ts b/x-pack/test/observability_functional/apps/observability/pages/cases/case_details.ts index 340131c14b6a13..96e989a9173e7e 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/cases/case_details.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/cases/case_details.ts @@ -17,7 +17,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const find = getService('find'); const PageObjects = getPageObjects(['common', 'header']); - describe('Cases', () => { + describe('Observability cases', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); @@ -56,6 +56,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { after(async () => { await cases.api.deleteAllCases(); + await observability.users.restoreDefaultTestUserRole(); }); it('should link to observability rule pages in case details', async () => { diff --git a/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts b/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts new file mode 100644 index 00000000000000..d1b6a2ce625196 --- /dev/null +++ b/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts @@ -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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +const ALL_ALERTS = 10; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const PageObjects = getPageObjects(['header']); + const esArchiver = getService('esArchiver'); + + describe('Observability overview', function () { + this.tags('includeFirefox'); + + const observability = getService('observability'); + const retry = getService('retry'); + + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); + }); + + describe('Without alerts', function () { + it('navigate and open alerts section', async () => { + await observability.overview.common.navigateToOverviewPage(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await observability.overview.common.openAlertsSectionAndWaitToAppear(); + }); + + it('should show no data message', async () => { + await retry.try(async () => { + await observability.overview.common.getAlertsTableNoDataOrFail(); + }); + }); + }); + + describe('With alerts', function () { + it('navigate and open alerts section', async () => { + await observability.overview.common.navigateToOverviewPageWithAlerts(); + await PageObjects.header.waitUntilLoadingHasFinished(); + await observability.overview.common.openAlertsSectionAndWaitToAppear(); + }); + + it('should show alerts correctly', async () => { + await retry.try(async () => { + const tableRows = await observability.alerts.common.getTableCellsInRows(); + expect(tableRows.length).to.be(ALL_ALERTS); + }); + }); + }); + }); +}; diff --git a/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts b/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts index 6d17b9c6e09208..6ab449873fc767 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/rule_details_page.ts @@ -45,7 +45,6 @@ export default ({ getService }: FtrProviderContext) => { const logThresholdRuleName = 'error-log'; before(async () => { - await observability.users.restoreDefaultTestUserRole(); const uptimeRule = { params: { search: '', @@ -82,6 +81,7 @@ export default ({ getService }: FtrProviderContext) => { uptimeRuleId = await createRule(uptimeRule); logThresholdRuleId = await createRule(logThresholdRule); }); + after(async () => { await deleteRuleById(uptimeRuleId); await deleteRuleById(logThresholdRuleId); diff --git a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts index a8b96c617db582..9ba2c69885b2a3 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/rules_page.ts @@ -171,6 +171,8 @@ export default ({ getService }: FtrProviderContext) => { 'No permissions prompt', async () => await testSubjects.exists('noPermissionPrompt') ); + + await observability.users.restoreDefaultTestUserRole(); }); }); }); From 01d28511e3cef4d964170194d61dfb8b7f095977 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Mon, 12 Sep 2022 14:33:37 +0200 Subject: [PATCH 057/144] [Enterprise Search] Grant connector API key monitor/main permissions (#140481) --- .../server/lib/indices/generate_api_key.test.ts | 6 +++--- .../server/lib/indices/generate_api_key.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.test.ts b/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.test.ts index 0ff9800716cfe3..6d49e2e53cfbad 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.test.ts @@ -56,7 +56,7 @@ describe('generateApiKey lib function', () => { name: 'index_name-connector', role_descriptors: { ['index-name-connector-role']: { - cluster: [], + cluster: ['monitor/main'], index: [ { names: ['index_name', `${CONNECTORS_INDEX}*`], @@ -91,7 +91,7 @@ describe('generateApiKey lib function', () => { name: 'index_name-connector', role_descriptors: { ['index-name-connector-role']: { - cluster: [], + cluster: ['monitor/main'], index: [ { names: ['index_name', `${CONNECTORS_INDEX}*`], @@ -138,7 +138,7 @@ describe('generateApiKey lib function', () => { name: 'index_name-connector', role_descriptors: { ['index-name-connector-role']: { - cluster: [], + cluster: ['monitor/main'], index: [ { names: ['index_name', `${CONNECTORS_INDEX}*`], diff --git a/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts b/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts index a6d3455f918974..f76fcf41fa2454 100644 --- a/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts +++ b/x-pack/plugins/enterprise_search/server/lib/indices/generate_api_key.ts @@ -16,7 +16,7 @@ export const generateApiKey = async (client: IScopedClusterClient, indexName: st name: `${indexName}-connector`, role_descriptors: { [`${toAlphanumeric(indexName)}-connector-role`]: { - cluster: [], + cluster: ['monitor/main'], index: [ { names: [indexName, `${CONNECTORS_INDEX}*`], From d42e0e116631a2a43d8af2c1b4799a38ee1c494b Mon Sep 17 00:00:00 2001 From: Spencer <spencer@elastic.co> Date: Mon, 12 Sep 2022 08:04:51 -0500 Subject: [PATCH 058/144] [ftr/obs/alerts] refactor to avoid stale-element errors (#140427) * [ftr/obs/alerts] refactor to avoid stale-element errors * Revert "skip failing test suite (#140248)" This reverts commit b0b9b585fb1aa42a3078e67e6e8d1a3d3b68ae02. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- test/functional/services/common/find.ts | 4 +- test/functional/services/common/index.ts | 1 + .../services/common/retry_on_stale.ts | 44 ++++++--- test/functional/services/index.ts | 2 + .../services/observability/alerts/common.ts | 91 +++++++++---------- .../apps/observability/pages/alerts/index.ts | 3 +- 6 files changed, 77 insertions(+), 68 deletions(-) diff --git a/test/functional/services/common/find.ts b/test/functional/services/common/find.ts index da12279a3ffa10..ec2d5385a0a432 100644 --- a/test/functional/services/common/find.ts +++ b/test/functional/services/common/find.ts @@ -10,7 +10,6 @@ import { WebDriver, WebElement, By, until } from 'selenium-webdriver'; import { Browsers } from '../remote/browsers'; import { FtrService, FtrProviderContext } from '../../ftr_provider_context'; -import { retryOnStale } from './retry_on_stale'; import { WebElementWrapper } from '../lib/web_element_wrapper'; import { TimeoutOpt } from './types'; @@ -18,6 +17,7 @@ export class FindService extends FtrService { private readonly log = this.ctx.getService('log'); private readonly config = this.ctx.getService('config'); private readonly retry = this.ctx.getService('retry'); + private readonly retryOnStale = this.ctx.getService('retryOnStale'); private readonly WAIT_FOR_EXISTS_TIME = this.config.get('timeouts.waitForExists'); private readonly POLLING_TIME = 500; @@ -290,7 +290,7 @@ export class FindService extends FtrService { public async clickByCssSelectorWhenNotDisabled(selector: string, opts?: TimeoutOpt) { const timeout = opts?.timeout ?? this.defaultFindTimeout; - await retryOnStale(this.log, async () => { + await this.retryOnStale(async () => { this.log.debug(`Find.clickByCssSelectorWhenNotDisabled(${selector}, timeout=${timeout})`); const element = await this.byCssSelector(selector); diff --git a/test/functional/services/common/index.ts b/test/functional/services/common/index.ts index b7b8c67a4280d9..54c9e5a1ee54cc 100644 --- a/test/functional/services/common/index.ts +++ b/test/functional/services/common/index.ts @@ -14,3 +14,4 @@ export { PngService } from './png'; export { ScreenshotsService } from './screenshots'; export { SnapshotsService } from './snapshots'; export { TestSubjects } from './test_subjects'; +export { RetryOnStaleProvider } from './retry_on_stale'; diff --git a/test/functional/services/common/retry_on_stale.ts b/test/functional/services/common/retry_on_stale.ts index a240e8031cd685..4a190266458ec6 100644 --- a/test/functional/services/common/retry_on_stale.ts +++ b/test/functional/services/common/retry_on_stale.ts @@ -6,30 +6,44 @@ * Side Public License, v 1. */ -import { ToolingLog } from '@kbn/tooling-log'; +import { FtrProviderContext } from '../../ftr_provider_context'; const MAX_ATTEMPTS = 10; const isObj = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null; const errMsg = (err: unknown) => (isObj(err) && typeof err.message === 'string' ? err.message : ''); -export async function retryOnStale<T>(log: ToolingLog, fn: () => Promise<T>): Promise<T> { - let attempt = 0; - while (true) { - attempt += 1; - try { - return await fn(); - } catch (error) { - if (errMsg(error).includes('stale element reference')) { - if (attempt >= MAX_ATTEMPTS) { - throw new Error(`retryOnStale ran out of attempts after ${attempt} tries`); +export function RetryOnStaleProvider({ getService }: FtrProviderContext) { + const log = getService('log'); + + async function retryOnStale<T>(fn: () => Promise<T>): Promise<T> { + let attempt = 0; + while (true) { + attempt += 1; + try { + return await fn(); + } catch (error) { + if (errMsg(error).includes('stale element reference')) { + if (attempt >= MAX_ATTEMPTS) { + throw new Error(`retryOnStale ran out of attempts after ${attempt} tries`); + } + + log.warning('stale element exception caught, retrying'); + continue; } - log.warning('stale element exception caught, retrying'); - continue; + throw error; } - - throw error; } } + + retryOnStale.wrap = <Args extends any[], Result>(fn: (...args: Args) => Promise<Result>) => { + return async (...args: Args) => { + return await retryOnStale(async () => { + return await fn(...args); + }); + }; + }; + + return retryOnStale; } diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index 31d31e6424177e..e2186ddefa5faa 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -17,6 +17,7 @@ import { ScreenshotsService, SnapshotsService, TestSubjects, + RetryOnStaleProvider, } from './common'; import { ComboBoxService } from './combo_box'; import { @@ -88,4 +89,5 @@ export const services = { managementMenu: ManagementMenuService, monacoEditor: MonacoEditorService, menuToggle: MenuToggleService, + retryOnStale: RetryOnStaleProvider, }; diff --git a/x-pack/test/functional/services/observability/alerts/common.ts b/x-pack/test/functional/services/observability/alerts/common.ts index 6491c7a8b0595b..7a3f1f609a4031 100644 --- a/x-pack/test/functional/services/observability/alerts/common.ts +++ b/x-pack/test/functional/services/observability/alerts/common.ts @@ -36,6 +36,7 @@ export function ObservabilityAlertsCommonProvider({ const retry = getService('retry'); const toasts = getService('toasts'); const kibanaServer = getService('kibanaServer'); + const retryOnStale = getService('retryOnStale'); const navigateToTimeWithData = async () => { return await pageObjects.common.navigateToUrlWithBrowserHistory( @@ -108,14 +109,14 @@ export function ObservabilityAlertsCommonProvider({ return await find.allByCssSelector('.euiDataGridRowCell input[type="checkbox"]:enabled'); }; - const getTableCellsInRows = async () => { + const getTableCellsInRows = retryOnStale.wrap(async () => { const columnHeaders = await getTableColumnHeaders(); if (columnHeaders.length <= 0) { return []; } const cells = await getTableCells(); return chunk(cells, columnHeaders.length); - }; + }); const getTableOrFail = async () => { return await testSubjects.existOrFail(ALERTS_TABLE_CONTAINER_SELECTOR); @@ -134,37 +135,28 @@ export function ObservabilityAlertsCommonProvider({ return await testSubjects.find('queryInput'); }; - const getQuerySubmitButton = async () => { - return await testSubjects.find('querySubmitButton'); - }; - - const clearQueryBar = async () => { + const clearQueryBar = retryOnStale.wrap(async () => { return await (await getQueryBar()).clearValueWithKeyboard(); - }; + }); - const typeInQueryBar = async (query: string) => { + const typeInQueryBar = retryOnStale.wrap(async (query: string) => { return await (await getQueryBar()).type(query); - }; + }); const submitQuery = async (query: string) => { await typeInQueryBar(query); - return await (await getQuerySubmitButton()).click(); + await testSubjects.click('querySubmitButton'); }; // Flyout - const getViewAlertDetailsFlyoutButton = async () => { + const openAlertsFlyout = retryOnStale.wrap(async () => { await openActionsMenuForRow(0); - - return await testSubjects.find('viewAlertDetailsFlyout'); - }; - - const openAlertsFlyout = async () => { - await (await getViewAlertDetailsFlyoutButton()).click(); + await testSubjects.click('viewAlertDetailsFlyout'); await retry.waitFor( 'flyout open', async () => await testSubjects.exists(ALERTS_FLYOUT_SELECTOR, { timeout: 2500 }) ); - }; + }); const getAlertsFlyout = async () => { return await testSubjects.find(ALERTS_FLYOUT_SELECTOR); @@ -190,15 +182,19 @@ export function ObservabilityAlertsCommonProvider({ return await testSubjects.existOrFail('viewRuleDetailsFlyout'); }; - const getAlertsFlyoutDescriptionListTitles = async (): Promise<WebElementWrapper[]> => { - const flyout = await getAlertsFlyout(); - return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListTitle', flyout); - }; + const getAlertsFlyoutDescriptionListTitles = retryOnStale.wrap( + async (): Promise<WebElementWrapper[]> => { + const flyout = await getAlertsFlyout(); + return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListTitle', flyout); + } + ); - const getAlertsFlyoutDescriptionListDescriptions = async (): Promise<WebElementWrapper[]> => { - const flyout = await getAlertsFlyout(); - return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListDescription', flyout); - }; + const getAlertsFlyoutDescriptionListDescriptions = retryOnStale.wrap( + async (): Promise<WebElementWrapper[]> => { + const flyout = await getAlertsFlyout(); + return await testSubjects.findAllDescendant('alertsFlyoutDescriptionListDescription', flyout); + } + ); // Cell actions @@ -210,17 +206,19 @@ export function ObservabilityAlertsCommonProvider({ return await testSubjects.find(FILTER_FOR_VALUE_BUTTON_SELECTOR); }; - const openActionsMenuForRow = async (rowIndex: number) => { + const openActionsMenuForRow = retryOnStale.wrap(async (rowIndex: number) => { const actionsOverflowButton = await getActionsButtonByIndex(rowIndex); await actionsOverflowButton.click(); - }; + }); const viewRuleDetailsButtonClick = async () => { - return await (await testSubjects.find(VIEW_RULE_DETAILS_SELECTOR)).click(); + await testSubjects.click(VIEW_RULE_DETAILS_SELECTOR); }; + const viewRuleDetailsLinkClick = async () => { - return await (await testSubjects.find(VIEW_RULE_DETAILS_FLYOUT_SELECTOR)).click(); + await testSubjects.click(VIEW_RULE_DETAILS_FLYOUT_SELECTOR); }; + // Workflow status const setWorkflowStatusForRow = async (rowIndex: number, workflowStatus: WorkflowStatus) => { await openActionsMenuForRow(rowIndex); @@ -236,17 +234,14 @@ export function ObservabilityAlertsCommonProvider({ await toasts.dismissAllToasts(); }; - const setWorkflowStatusFilter = async (workflowStatus: WorkflowStatus) => { - const buttonGroupButton = await testSubjects.find( - `workflowStatusFilterButton-${workflowStatus}` - ); - await buttonGroupButton.click(); - }; + const setWorkflowStatusFilter = retryOnStale.wrap(async (workflowStatus: WorkflowStatus) => { + await testSubjects.click(`workflowStatusFilterButton-${workflowStatus}`); + }); - const getWorkflowStatusFilterValue = async () => { + const getWorkflowStatusFilterValue = retryOnStale.wrap(async () => { const selectedWorkflowStatusButton = await find.byClassName('euiButtonGroupButton-isSelected'); return await selectedWorkflowStatusButton.getVisibleText(); - }; + }); // Alert status const setAlertStatusFilter = async (alertStatus?: AlertStatus) => { @@ -257,8 +252,8 @@ export function ObservabilityAlertsCommonProvider({ if (alertStatus === ALERT_STATUS_RECOVERED) { buttonSubject = 'alert-status-filter-recovered-button'; } - const buttonGroupButton = await testSubjects.find(buttonSubject); - await buttonGroupButton.click(); + + await testSubjects.click(buttonSubject); }; const alertDataIsBeingLoaded = async () => { @@ -277,14 +272,12 @@ export function ObservabilityAlertsCommonProvider({ const isAbsoluteRange = await testSubjects.exists('superDatePickerstartDatePopoverButton'); if (isAbsoluteRange) { - const startButton = await testSubjects.find('superDatePickerstartDatePopoverButton'); - const endButton = await testSubjects.find('superDatePickerendDatePopoverButton'); - return `${await startButton.getVisibleText()} - ${await endButton.getVisibleText()}`; + const startText = await testSubjects.getVisibleText('superDatePickerstartDatePopoverButton'); + const endText = await testSubjects.getVisibleText('superDatePickerendDatePopoverButton'); + return `${startText} - ${endText}`; } - const datePickerButton = await testSubjects.find('superDatePickerShowDatesButton'); - const buttonText = await datePickerButton.getVisibleText(); - return buttonText; + return await testSubjects.getVisibleText('superDatePickerShowDatesButton'); }; const getActionsButtonByIndex = async (index: number) => { @@ -294,14 +287,14 @@ export function ObservabilityAlertsCommonProvider({ return actionsOverflowButtons[index] || null; }; - const getRuleStatValue = async (testSubj: string) => { + const getRuleStatValue = retryOnStale.wrap(async (testSubj: string) => { const stat = await testSubjects.find(testSubj); const title = await stat.findByCssSelector('.euiStat__title'); const count = await title.getVisibleText(); const value = Number.parseInt(count, 10); expect(Number.isNaN(value)).to.be(false); return value; - }; + }); return { getQueryBar, diff --git a/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts b/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts index f2a59d6b22b2e7..cdb0ea37a6417c 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/alerts/index.ts @@ -20,8 +20,7 @@ export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const find = getService('find'); - // Failing: See https://github.com/elastic/kibana/issues/140248 - describe.skip('Observability alerts', function () { + describe('Observability alerts', function () { this.tags('includeFirefox'); const testSubjects = getService('testSubjects'); From 0cf0e3dd97d92b2bb108ed6522b85b623f6c280d Mon Sep 17 00:00:00 2001 From: Ying Mao <ying.mao@elastic.co> Date: Mon, 12 Sep 2022 09:35:54 -0400 Subject: [PATCH 059/144] [Response Ops] Keep task document when enabling/disabling rules (#139826) * wip * wip * Fixing types and adding unit tests for task manager disable * Updating to enable/disable. Update rules client to use new fns * Updating unit tests. Fixing enable to still schedule task if necessary * Adding functional test for task manager migration * Fixing query. Updating functional tests * Setting scheduledTaskId to null on disable only if it does not match rule id * Updating README * Fixing tests * Task manager runner doesn't overwrite enabled on update * Updating migration to set enabled: false for failed and unrecognized tasks * Fixing tests * PR feedback Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/rules_client/rules_client.ts | 40 ++- .../server/rules_client/tests/create.test.ts | 1 + .../server/rules_client/tests/disable.test.ts | 153 +++++++-- .../server/rules_client/tests/enable.test.ts | 301 +++++++++++------- .../rules_client_conflict_retries.test.ts | 6 +- x-pack/plugins/task_manager/README.md | 30 ++ x-pack/plugins/task_manager/server/index.ts | 2 +- x-pack/plugins/task_manager/server/mocks.ts | 1 + x-pack/plugins/task_manager/server/plugin.ts | 2 + .../mark_available_tasks_as_claimed.test.ts | 14 + .../mark_available_tasks_as_claimed.ts | 12 + .../server/queries/task_claiming.test.ts | 33 ++ .../server/queries/task_claiming.ts | 3 + .../server/saved_objects/mappings.json | 3 + .../server/saved_objects/migrations.test.ts | 41 +++ .../server/saved_objects/migrations.ts | 18 ++ x-pack/plugins/task_manager/server/task.ts | 10 +- .../server/task_running/task_runner.test.ts | 36 +++ .../server/task_running/task_runner.ts | 14 +- .../server/task_scheduling.mock.ts | 1 + .../server/task_scheduling.test.ts | 183 +++++++++++ .../task_manager/server/task_scheduling.ts | 78 ++++- .../common/lib/task_manager_utils.ts | 42 +++ .../group1/tests/alerting/create.ts | 1 + .../group1/tests/alerting/disable.ts | 112 ++++--- .../group1/tests/alerting/enable.ts | 2 + .../group2/tests/alerting/alerts.ts | 28 +- .../spaces_only/tests/alerting/create.ts | 2 + .../spaces_only/tests/alerting/disable.ts | 38 ++- .../spaces_only/tests/alerting/enable.ts | 2 + .../tests/alerting/scheduled_task_id.ts | 1 + .../test_suites/task_manager/migrations.ts | 54 ++++ .../task_manager/task_management.ts | 4 +- 33 files changed, 1036 insertions(+), 232 deletions(-) diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index f0cf88615047dc..7d0f6463a48721 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -384,7 +384,7 @@ export interface GetActionErrorLogByIdParams { sort: estypes.Sort; } -interface ScheduleRuleOptions { +interface ScheduleTaskOptions { id: string; consumer: string; ruleTypeId: string; @@ -589,7 +589,7 @@ export class RulesClient { if (data.enabled) { let scheduledTask; try { - scheduledTask = await this.scheduleRule({ + scheduledTask = await this.scheduleTask({ id: createdAlert.id, consumer: data.consumer, ruleTypeId: rawRule.alertTypeId, @@ -2138,7 +2138,24 @@ export class RulesClient { } catch (e) { throw e; } - const scheduledTask = await this.scheduleRule({ + } + + let scheduledTaskIdToCreate: string | null = null; + if (attributes.scheduledTaskId) { + // If scheduledTaskId defined in rule SO, make sure it exists + try { + await this.taskManager.get(attributes.scheduledTaskId); + } catch (err) { + scheduledTaskIdToCreate = id; + } + } else { + // If scheduledTaskId doesn't exist in rule SO, set it to rule ID + scheduledTaskIdToCreate = id; + } + + if (scheduledTaskIdToCreate) { + // Schedule the task if it doesn't exist + const scheduledTask = await this.scheduleTask({ id, consumer: attributes.consumer, ruleTypeId: attributes.alertTypeId, @@ -2148,6 +2165,9 @@ export class RulesClient { await this.unsecuredSavedObjectsClient.update('alert', id, { scheduledTaskId: scheduledTask.id, }); + } else { + // Task exists so set enabled to true + await this.taskManager.bulkEnableDisable([attributes.scheduledTaskId!], true); } } @@ -2282,14 +2302,21 @@ export class RulesClient { this.updateMeta({ ...attributes, enabled: false, - scheduledTaskId: null, + scheduledTaskId: attributes.scheduledTaskId === id ? attributes.scheduledTaskId : null, updatedBy: await this.getUserName(), updatedAt: new Date().toISOString(), }), { version } ); + + // If the scheduledTaskId does not match the rule id, we should + // remove the task, otherwise mark the task as disabled if (attributes.scheduledTaskId) { - await this.taskManager.removeIfExists(attributes.scheduledTaskId); + if (attributes.scheduledTaskId !== id) { + await this.taskManager.removeIfExists(attributes.scheduledTaskId); + } else { + await this.taskManager.bulkEnableDisable([attributes.scheduledTaskId], false); + } } } } @@ -2767,7 +2794,7 @@ export class RulesClient { return this.spaceId; } - private async scheduleRule(opts: ScheduleRuleOptions) { + private async scheduleTask(opts: ScheduleTaskOptions) { const { id, consumer, ruleTypeId, schedule, throwOnConflict } = opts; const taskInstance = { id, // use the same ID for task document as the rule @@ -2784,6 +2811,7 @@ export class RulesClient { alertInstances: {}, }, scope: ['alerting'], + enabled: true, }; try { return await this.taskManager.schedule(taskInstance); diff --git a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts index b29d41f183b735..f5192bf6cbe659 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/create.test.ts @@ -463,6 +463,7 @@ describe('create()', () => { expect(taskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(` Array [ Object { + "enabled": true, "id": "1", "params": Object { "alertId": "1", diff --git a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts index a193733aff26fa..499f1c2e8454dc 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/disable.test.ts @@ -60,7 +60,7 @@ const rulesClientParams: jest.Mocked<ConstructorOptions> = { beforeEach(() => { getBeforeSetup(rulesClientParams, taskManager, ruleTypeRegistry); taskManager.get.mockResolvedValue({ - id: 'task-123', + id: '1', taskType: 'alerting:123', scheduledAt: new Date(), attempts: 1, @@ -81,7 +81,7 @@ setGlobalDate(); describe('disable()', () => { let rulesClient: RulesClient; - const existingAlert = { + const existingRule = { id: '1', type: 'alert', attributes: { @@ -89,7 +89,7 @@ describe('disable()', () => { schedule: { interval: '10s' }, alertTypeId: 'myType', enabled: true, - scheduledTaskId: 'task-123', + scheduledTaskId: '1', actions: [ { group: 'default', @@ -105,10 +105,10 @@ describe('disable()', () => { version: '123', references: [], }; - const existingDecryptedAlert = { - ...existingAlert, + const existingDecryptedRule = { + ...existingRule, attributes: { - ...existingAlert.attributes, + ...existingRule.attributes, apiKey: Buffer.from('123:abc').toString('base64'), apiKeyOwner: 'elastic', }, @@ -118,12 +118,12 @@ describe('disable()', () => { beforeEach(() => { rulesClient = new RulesClient(rulesClientParams); - unsecuredSavedObjectsClient.get.mockResolvedValue(existingAlert); - encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValue(existingDecryptedAlert); + unsecuredSavedObjectsClient.get.mockResolvedValue(existingRule); + encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValue(existingDecryptedRule); }); describe('authorization', () => { - test('ensures user is authorised to disable this type of alert under the consumer', async () => { + test('ensures user is authorised to disable this type of rule under the consumer', async () => { await rulesClient.disable({ id: '1' }); expect(authorization.ensureAuthorized).toHaveBeenCalledWith({ @@ -134,7 +134,7 @@ describe('disable()', () => { }); }); - test('throws when user is not authorised to disable this type of alert', async () => { + test('throws when user is not authorised to disable this type of rule', async () => { authorization.ensureAuthorized.mockRejectedValue( new Error(`Unauthorized to disable a "myType" alert for "myApp"`) ); @@ -191,7 +191,7 @@ describe('disable()', () => { }); }); - test('disables an alert', async () => { + test('disables an rule', async () => { await rulesClient.disable({ id: '1' }); expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { @@ -208,7 +208,7 @@ describe('disable()', () => { meta: { versionApiKeyLastmodified: 'v7.10.0', }, - scheduledTaskId: null, + scheduledTaskId: '1', apiKey: 'MTIzOmFiYw==', apiKeyOwner: 'elastic', updatedAt: '2019-02-12T21:01:22.479Z', @@ -229,11 +229,12 @@ describe('disable()', () => { version: '123', } ); - expect(taskManager.removeIfExists).toHaveBeenCalledWith('task-123'); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['1'], false); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); }); test('disables the rule with calling event log to "recover" the alert instances from the task state', async () => { - const scheduledTaskId = 'task-123'; + const scheduledTaskId = '1'; taskManager.get.mockResolvedValue({ id: scheduledTaskId, taskType: 'alerting:123', @@ -278,7 +279,7 @@ describe('disable()', () => { meta: { versionApiKeyLastmodified: 'v7.10.0', }, - scheduledTaskId: null, + scheduledTaskId: '1', apiKey: 'MTIzOmFiYw==', apiKeyOwner: 'elastic', updatedAt: '2019-02-12T21:01:22.479Z', @@ -299,7 +300,8 @@ describe('disable()', () => { version: '123', } ); - expect(taskManager.removeIfExists).toHaveBeenCalledWith('task-123'); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['1'], false); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); expect(eventLogger.logEvent).toHaveBeenCalledTimes(1); expect(eventLogger.logEvent.mock.calls[0][0]).toStrictEqual({ @@ -359,7 +361,7 @@ describe('disable()', () => { meta: { versionApiKeyLastmodified: 'v7.10.0', }, - scheduledTaskId: null, + scheduledTaskId: '1', apiKey: 'MTIzOmFiYw==', apiKeyOwner: 'elastic', updatedAt: '2019-02-12T21:01:22.479Z', @@ -380,7 +382,8 @@ describe('disable()', () => { version: '123', } ); - expect(taskManager.removeIfExists).toHaveBeenCalledWith('task-123'); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['1'], false); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); expect(eventLogger.logEvent).toHaveBeenCalledTimes(0); expect(rulesClientParams.logger.warn).toHaveBeenCalledWith( @@ -403,7 +406,7 @@ describe('disable()', () => { schedule: { interval: '10s' }, alertTypeId: 'myType', enabled: false, - scheduledTaskId: null, + scheduledTaskId: '1', updatedAt: '2019-02-12T21:01:22.479Z', updatedBy: 'elastic', actions: [ @@ -422,14 +425,15 @@ describe('disable()', () => { version: '123', } ); - expect(taskManager.removeIfExists).toHaveBeenCalledWith('task-123'); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['1'], false); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); }); - test(`doesn't disable already disabled alerts`, async () => { + test(`doesn't disable already disabled rules`, async () => { encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValueOnce({ - ...existingDecryptedAlert, + ...existingDecryptedRule, attributes: { - ...existingDecryptedAlert.attributes, + ...existingDecryptedRule.attributes, actions: [], enabled: false, }, @@ -437,7 +441,8 @@ describe('disable()', () => { await rulesClient.disable({ id: '1' }); expect(unsecuredSavedObjectsClient.update).not.toHaveBeenCalled(); - expect(taskManager.removeIfExists).not.toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); }); test('swallows error when failing to load decrypted saved object', async () => { @@ -445,7 +450,8 @@ describe('disable()', () => { await rulesClient.disable({ id: '1' }); expect(unsecuredSavedObjectsClient.update).toHaveBeenCalled(); - expect(taskManager.removeIfExists).toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).toHaveBeenCalled(); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); expect(rulesClientParams.logger.error).toHaveBeenCalledWith( 'disable(): Failed to load API key of alert 1: Fail' ); @@ -457,13 +463,106 @@ describe('disable()', () => { await expect(rulesClient.disable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot( `"Failed to update"` ); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); }); - test('throws when failing to remove task from task manager', async () => { - taskManager.removeIfExists.mockRejectedValueOnce(new Error('Failed to remove task')); + test('throws when failing to disable task', async () => { + taskManager.bulkEnableDisable.mockRejectedValueOnce(new Error('Failed to disable task')); + await expect(rulesClient.disable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot( + `"Failed to disable task"` + ); + expect(taskManager.removeIfExists).not.toHaveBeenCalledWith(); + }); + + test('removes task document if scheduled task id does not match rule id', async () => { + encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValue({ + ...existingRule, + attributes: { + ...existingRule.attributes, + scheduledTaskId: 'task-123', + }, + }); + await rulesClient.disable({ id: '1' }); + expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); + expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { + namespace: 'default', + }); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith( + 'alert', + '1', + { + consumer: 'myApp', + schedule: { interval: '10s' }, + alertTypeId: 'myType', + enabled: false, + scheduledTaskId: null, + updatedAt: '2019-02-12T21:01:22.479Z', + updatedBy: 'elastic', + actions: [ + { + group: 'default', + id: '1', + actionTypeId: '1', + actionRef: '1', + params: { + foo: true, + }, + }, + ], + }, + { + version: '123', + } + ); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); + expect(taskManager.removeIfExists).toHaveBeenCalledWith('task-123'); + }); + + test('throws when failing to remove existing task', async () => { + encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValue({ + ...existingRule, + attributes: { + ...existingRule.attributes, + scheduledTaskId: 'task-123', + }, + }); + taskManager.removeIfExists.mockRejectedValueOnce(new Error('Failed to remove task')); await expect(rulesClient.disable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot( `"Failed to remove task"` ); + expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); + expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { + namespace: 'default', + }); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith( + 'alert', + '1', + { + consumer: 'myApp', + schedule: { interval: '10s' }, + alertTypeId: 'myType', + enabled: false, + scheduledTaskId: null, + updatedAt: '2019-02-12T21:01:22.479Z', + updatedBy: 'elastic', + actions: [ + { + group: 'default', + id: '1', + actionTypeId: '1', + actionRef: '1', + params: { + foo: true, + }, + }, + ], + }, + { + version: '123', + } + ); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/alerting/server/rules_client/tests/enable.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/enable.test.ts index 8923031ab6b87d..b8d259bd6a6829 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/enable.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/enable.test.ts @@ -63,6 +63,7 @@ describe('enable()', () => { consumer: 'myApp', schedule: { interval: '10s' }, alertTypeId: 'myType', + scheduledTaskId: 'task-123', enabled: false, apiKey: 'MTIzOmFiYw==', apiKeyOwner: 'elastic', @@ -91,7 +92,25 @@ describe('enable()', () => { }, }; + const mockTask = { + id: 'task-123', + taskType: 'alerting:123', + scheduledAt: new Date(), + attempts: 1, + status: TaskStatus.Idle, + runAt: new Date(), + startedAt: null, + retryAt: null, + state: {}, + params: { + alertId: '1', + }, + ownerId: null, + enabled: false, + }; + beforeEach(() => { + jest.resetAllMocks(); getBeforeSetup(rulesClientParams, taskManager, ruleTypeRegistry); (auditLogger.log as jest.Mock).mockClear(); rulesClient = new RulesClient(rulesClientParams); @@ -100,19 +119,7 @@ describe('enable()', () => { rulesClientParams.createAPIKey.mockResolvedValue({ apiKeysEnabled: false, }); - taskManager.schedule.mockResolvedValue({ - id: '1', - scheduledAt: new Date(), - attempts: 0, - status: TaskStatus.Idle, - runAt: new Date(), - state: {}, - params: {}, - taskType: '', - startedAt: null, - retryAt: null, - ownerId: null, - }); + taskManager.get.mockResolvedValue(mockTask); }); describe('authorization', () => { @@ -208,6 +215,7 @@ describe('enable()', () => { updatedBy: 'elastic', apiKey: 'MTIzOmFiYw==', apiKeyOwner: 'elastic', + scheduledTaskId: 'task-123', actions: [ { group: 'default', @@ -231,27 +239,7 @@ describe('enable()', () => { version: '123', } ); - expect(taskManager.schedule).toHaveBeenCalledWith({ - id: '1', - taskType: `alerting:myType`, - params: { - alertId: '1', - spaceId: 'default', - consumer: 'myApp', - }, - schedule: { - interval: '10s', - }, - state: { - alertInstances: {}, - alertTypeState: {}, - previousStartedAt: null, - }, - scope: ['alerting'], - }); - expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith('alert', '1', { - scheduledTaskId: '1', - }); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['task-123'], true); }); test('enables a rule that does not have an apiKey', async () => { @@ -283,6 +271,7 @@ describe('enable()', () => { updatedBy: 'elastic', apiKey: 'MTIzOmFiYw==', apiKeyOwner: 'elastic', + scheduledTaskId: 'task-123', actions: [ { group: 'default', @@ -306,9 +295,10 @@ describe('enable()', () => { version: '123', } ); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['task-123'], true); }); - test(`doesn't enable already enabled alerts`, async () => { + test(`doesn't update already enabled alerts but ensures task is enabled`, async () => { encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValueOnce({ ...existingRuleWithoutApiKey, attributes: { @@ -321,7 +311,7 @@ describe('enable()', () => { expect(rulesClientParams.getUserName).not.toHaveBeenCalled(); expect(rulesClientParams.createAPIKey).not.toHaveBeenCalled(); expect(unsecuredSavedObjectsClient.create).not.toHaveBeenCalled(); - expect(taskManager.schedule).not.toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['task-123'], true); }); test('sets API key when createAPIKey returns one', async () => { @@ -345,6 +335,7 @@ describe('enable()', () => { }, apiKey: Buffer.from('123:abc').toString('base64'), apiKeyOwner: 'elastic', + scheduledTaskId: 'task-123', updatedBy: 'elastic', updatedAt: '2019-02-12T21:01:22.479Z', actions: [ @@ -370,6 +361,7 @@ describe('enable()', () => { version: '123', } ); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['task-123'], true); }); test('throws an error if API key creation throws', async () => { @@ -381,6 +373,7 @@ describe('enable()', () => { await expect( async () => await rulesClient.enable({ id: '1' }) ).rejects.toThrowErrorMatchingInlineSnapshot(`"Error creating API key for rule: no"`); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); }); test('falls back when failing to getDecryptedAsInternalUser', async () => { @@ -391,6 +384,7 @@ describe('enable()', () => { expect(rulesClientParams.logger.error).toHaveBeenCalledWith( 'enable(): Failed to load API key of alert 1: Fail' ); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['task-123'], true); }); test('throws error when failing to load the saved object using SOC', async () => { @@ -403,10 +397,10 @@ describe('enable()', () => { expect(rulesClientParams.getUserName).not.toHaveBeenCalled(); expect(rulesClientParams.createAPIKey).not.toHaveBeenCalled(); expect(unsecuredSavedObjectsClient.update).not.toHaveBeenCalled(); - expect(taskManager.schedule).not.toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); }); - test('throws error when failing to update the first time', async () => { + test('throws when unsecuredSavedObjectsClient update fails', async () => { rulesClientParams.createAPIKey.mockResolvedValueOnce({ apiKeysEnabled: true, result: { id: '123', name: '123', api_key: 'abc' }, @@ -419,100 +413,102 @@ describe('enable()', () => { ); expect(rulesClientParams.getUserName).toHaveBeenCalled(); expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(taskManager.schedule).not.toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); }); - test('throws error when failing to update the second time', async () => { - unsecuredSavedObjectsClient.update.mockReset(); - unsecuredSavedObjectsClient.update.mockResolvedValueOnce({ - ...existingRuleWithoutApiKey, - attributes: { - ...existingRuleWithoutApiKey.attributes, - enabled: true, - }, + test('enables task when scheduledTaskId is defined and task exists', async () => { + await rulesClient.enable({ id: '1' }); + expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); + expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { + namespace: 'default', }); - unsecuredSavedObjectsClient.update.mockRejectedValueOnce( - new Error('Fail to update second time') - ); - - await expect(rulesClient.enable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot( - `"Fail to update second time"` - ); - expect(rulesClientParams.getUserName).toHaveBeenCalled(); - expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledTimes(2); - expect(taskManager.schedule).toHaveBeenCalled(); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).toHaveBeenCalledWith(['task-123'], true); }); - test('throws error when failing to schedule task', async () => { - taskManager.schedule.mockRejectedValueOnce(new Error('Fail to schedule')); - + test('throws error when enabling task fails', async () => { + taskManager.bulkEnableDisable.mockRejectedValueOnce(new Error('Failed to enable task')); await expect(rulesClient.enable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot( - `"Fail to schedule"` + `"Failed to enable task"` ); - expect(rulesClientParams.getUserName).toHaveBeenCalled(); + expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); + expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { + namespace: 'default', + }); expect(unsecuredSavedObjectsClient.update).toHaveBeenCalled(); }); - test('enables a rule if conflict errors received when scheduling a task', async () => { - unsecuredSavedObjectsClient.create.mockResolvedValueOnce({ - ...existingRuleWithoutApiKey, - attributes: { - ...existingRuleWithoutApiKey.attributes, - enabled: true, - apiKey: null, - apiKeyOwner: null, - updatedBy: 'elastic', - }, + test('schedules task when scheduledTaskId is defined but task with that ID does not', async () => { + taskManager.schedule.mockResolvedValueOnce({ + id: '1', + taskType: 'alerting:123', + scheduledAt: new Date(), + attempts: 1, + status: TaskStatus.Idle, + runAt: new Date(), + startedAt: null, + retryAt: null, + state: {}, + params: {}, + ownerId: null, }); - taskManager.schedule.mockRejectedValueOnce( - Object.assign(new Error('Conflict!'), { statusCode: 409 }) - ); - + taskManager.get.mockRejectedValueOnce(new Error('Failed to get task!')); await rulesClient.enable({ id: '1' }); expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { namespace: 'default', }); - expect(unsecuredSavedObjectsClient.create).not.toBeCalledWith('api_key_pending_invalidation'); - expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith( - 'alert', - '1', - { - name: 'name', - schedule: { interval: '10s' }, - alertTypeId: 'myType', + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledTimes(2); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); + expect(taskManager.schedule).toHaveBeenCalledWith({ + id: '1', + taskType: `alerting:myType`, + params: { + alertId: '1', + spaceId: 'default', consumer: 'myApp', - enabled: true, - meta: { - versionApiKeyLastmodified: kibanaVersion, - }, - updatedAt: '2019-02-12T21:01:22.479Z', - updatedBy: 'elastic', - apiKey: 'MTIzOmFiYw==', - apiKeyOwner: 'elastic', - actions: [ - { - group: 'default', - id: '1', - actionTypeId: '1', - actionRef: '1', - params: { - foo: true, - }, - }, - ], - executionStatus: { - status: 'pending', - lastDuration: 0, - lastExecutionDate: '2019-02-12T21:01:22.479Z', - error: null, - warning: null, - }, }, - { - version: '123', - } - ); + schedule: { + interval: '10s', + }, + enabled: true, + state: { + alertInstances: {}, + alertTypeState: {}, + previousStartedAt: null, + }, + scope: ['alerting'], + }); + expect(unsecuredSavedObjectsClient.update).toHaveBeenNthCalledWith(2, 'alert', '1', { + scheduledTaskId: '1', + }); + }); + + test('schedules task when scheduledTaskId is not defined', async () => { + encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValueOnce({ + ...existingRule, + attributes: { ...existingRule.attributes, scheduledTaskId: null }, + }); + taskManager.schedule.mockResolvedValueOnce({ + id: '1', + taskType: 'alerting:123', + scheduledAt: new Date(), + attempts: 1, + status: TaskStatus.Idle, + runAt: new Date(), + startedAt: null, + retryAt: null, + state: {}, + params: {}, + ownerId: null, + }); + await rulesClient.enable({ id: '1' }); + expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); + expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { + namespace: 'default', + }); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledTimes(2); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); expect(taskManager.schedule).toHaveBeenCalledWith({ id: '1', taskType: `alerting:myType`, @@ -524,6 +520,7 @@ describe('enable()', () => { schedule: { interval: '10s', }, + enabled: true, state: { alertInstances: {}, alertTypeState: {}, @@ -531,7 +528,81 @@ describe('enable()', () => { }, scope: ['alerting'], }); - expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledWith('alert', '1', { + expect(unsecuredSavedObjectsClient.update).toHaveBeenNthCalledWith(2, 'alert', '1', { + scheduledTaskId: '1', + }); + }); + + test('throws error when scheduling task fails', async () => { + encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValueOnce({ + ...existingRule, + attributes: { ...existingRule.attributes, scheduledTaskId: null }, + }); + taskManager.schedule.mockRejectedValueOnce(new Error('Fail to schedule')); + await expect(rulesClient.enable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot( + `"Fail to schedule"` + ); + expect(rulesClientParams.getUserName).toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); + expect(taskManager.schedule).toHaveBeenCalled(); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledTimes(1); + }); + + test('succeeds if conflict errors received when scheduling a task', async () => { + encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValueOnce({ + ...existingRule, + attributes: { ...existingRule.attributes, scheduledTaskId: null }, + }); + taskManager.schedule.mockRejectedValueOnce( + Object.assign(new Error('Conflict!'), { statusCode: 409 }) + ); + await rulesClient.enable({ id: '1' }); + expect(unsecuredSavedObjectsClient.get).not.toHaveBeenCalled(); + expect(encryptedSavedObjects.getDecryptedAsInternalUser).toHaveBeenCalledWith('alert', '1', { + namespace: 'default', + }); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledTimes(2); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); + expect(taskManager.schedule).toHaveBeenCalled(); + }); + + test('throws error when update after scheduling task fails', async () => { + encryptedSavedObjects.getDecryptedAsInternalUser.mockResolvedValueOnce({ + ...existingRule, + attributes: { ...existingRule.attributes, scheduledTaskId: null }, + }); + taskManager.schedule.mockResolvedValueOnce({ + id: '1', + taskType: 'alerting:123', + scheduledAt: new Date(), + attempts: 1, + status: TaskStatus.Idle, + runAt: new Date(), + startedAt: null, + retryAt: null, + state: {}, + params: {}, + ownerId: null, + }); + unsecuredSavedObjectsClient.update.mockResolvedValueOnce({ + ...existingRule, + attributes: { + ...existingRule.attributes, + enabled: true, + }, + }); + unsecuredSavedObjectsClient.update.mockRejectedValueOnce( + new Error('Fail to update after scheduling task') + ); + + await expect(rulesClient.enable({ id: '1' })).rejects.toThrowErrorMatchingInlineSnapshot( + `"Fail to update after scheduling task"` + ); + expect(rulesClientParams.getUserName).toHaveBeenCalled(); + expect(unsecuredSavedObjectsClient.update).toHaveBeenCalledTimes(2); + expect(taskManager.schedule).toHaveBeenCalled(); + expect(taskManager.bulkEnableDisable).not.toHaveBeenCalled(); + expect(unsecuredSavedObjectsClient.update).toHaveBeenNthCalledWith(2, 'alert', '1', { scheduledTaskId: '1', }); }); diff --git a/x-pack/plugins/alerting/server/rules_client_conflict_retries.test.ts b/x-pack/plugins/alerting/server/rules_client_conflict_retries.test.ts index 2416e95c38f648..b71cc0276dc646 100644 --- a/x-pack/plugins/alerting/server/rules_client_conflict_retries.test.ts +++ b/x-pack/plugins/alerting/server/rules_client_conflict_retries.test.ts @@ -141,9 +141,9 @@ async function enable(success: boolean) { return expectConflict(success, err); } - // a successful enable call makes 2 calls to update, so that's 3 total, - // 1 with conflict + 2 on success - expectSuccess(success, 3); + // a successful enable call makes 1 call to update, so with + // conflict, we would expect 1 on conflict, 1 on success + expectSuccess(success, 2); } async function disable(success: boolean) { diff --git a/x-pack/plugins/task_manager/README.md b/x-pack/plugins/task_manager/README.md index 4a99889ad9cc31..59f836c10c03eb 100644 --- a/x-pack/plugins/task_manager/README.md +++ b/x-pack/plugins/task_manager/README.md @@ -328,6 +328,9 @@ The _Start_ Plugin api allow you to use Task Manager to facilitate your Plugin's runSoon: (taskId: string) => { // ... }, + bulkEnableDisable: (taskIds: string[], enabled: boolean) => { + // ... + }, bulkUpdateSchedules: (taskIds: string[], schedule: IntervalSchedule) => { // ... }, @@ -418,6 +421,33 @@ export class Plugin { } ``` +#### bulkEnableDisable +Using `bulkEnableDisable` you can instruct TaskManger to update the `enabled` status of tasks. + +Example: +```js +export class Plugin { + constructor() { + } + + public setup(core: CoreSetup, plugins: { taskManager }) { + } + + public start(core: CoreStart, plugins: { taskManager }) { + try { + const bulkDisableResults = await taskManager.bulkEnableDisable( + ['97c2c4e7-d850-11ec-bf95-895ffd19f959', 'a5ee24d1-dce2-11ec-ab8d-cf74da82133d'], + false, + ); + // If no error is thrown, the bulkEnableDisable has completed successfully. + // But some updates of some tasks can be failed, due to OCC 409 conflict for example + } catch(err: Error) { + // if error is caught, means the whole method requested has failed and tasks weren't updated + } + } +} +``` + #### bulkUpdateSchedules Using `bulkUpdatesSchedules` you can instruct TaskManger to update interval of tasks that are in `idle` status (for the tasks which have `running` status, `schedule` and `runAt` will be recalculated after task run finishes). diff --git a/x-pack/plugins/task_manager/server/index.ts b/x-pack/plugins/task_manager/server/index.ts index 0b01d6a05b7e1b..4f1d41cad2109d 100644 --- a/x-pack/plugins/task_manager/server/index.ts +++ b/x-pack/plugins/task_manager/server/index.ts @@ -30,7 +30,7 @@ export { throwUnrecoverableError, isEphemeralTaskRejectedDueToCapacityError, } from './task_running'; -export type { RunNowResult, BulkUpdateSchedulesResult } from './task_scheduling'; +export type { RunNowResult, BulkUpdateTaskResult } from './task_scheduling'; export { getOldestIdleActionTask } from './queries/oldest_idle_action_task'; export { IdleTaskWithExpiredRunAt, diff --git a/x-pack/plugins/task_manager/server/mocks.ts b/x-pack/plugins/task_manager/server/mocks.ts index 1560c20be5baa5..9ce4797e50db96 100644 --- a/x-pack/plugins/task_manager/server/mocks.ts +++ b/x-pack/plugins/task_manager/server/mocks.ts @@ -30,6 +30,7 @@ const createStartMock = () => { supportsEphemeralTasks: jest.fn(), bulkUpdateSchedules: jest.fn(), bulkSchedule: jest.fn(), + bulkEnableDisable: jest.fn(), }; return mock; }; diff --git a/x-pack/plugins/task_manager/server/plugin.ts b/x-pack/plugins/task_manager/server/plugin.ts index 2bb06b3a223be3..08b7a2908f2e8a 100644 --- a/x-pack/plugins/task_manager/server/plugin.ts +++ b/x-pack/plugins/task_manager/server/plugin.ts @@ -53,6 +53,7 @@ export type TaskManagerStartContract = Pick< | 'ephemeralRunNow' | 'ensureScheduled' | 'bulkUpdateSchedules' + | 'bulkEnableDisable' | 'bulkSchedule' > & Pick<TaskStore, 'fetch' | 'aggregate' | 'get' | 'remove'> & { @@ -251,6 +252,7 @@ export class TaskManagerPlugin bulkSchedule: (...args) => taskScheduling.bulkSchedule(...args), ensureScheduled: (...args) => taskScheduling.ensureScheduled(...args), runSoon: (...args) => taskScheduling.runSoon(...args), + bulkEnableDisable: (...args) => taskScheduling.bulkEnableDisable(...args), bulkUpdateSchedules: (...args) => taskScheduling.bulkUpdateSchedules(...args), ephemeralRunNow: (task: EphemeralTask) => taskScheduling.ephemeralRunNow(task), supportsEphemeralTasks: () => diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts index 086a435a39fa9e..4b04672615b7d2 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.test.ts @@ -13,6 +13,7 @@ import { IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt, SortByRunAtAndRetryAt, + EnabledTask, } from './mark_available_tasks_as_claimed'; import { TaskTypeDictionary } from '../task_type_dictionary'; @@ -53,6 +54,8 @@ describe('mark_available_tasks_as_claimed', () => { expect({ query: mustBeAllOf( + // Task must be enabled + EnabledTask, // Either a task with idle status and runAt <= now or // status running or claiming with a retryAt <= now. shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt) @@ -72,6 +75,17 @@ describe('mark_available_tasks_as_claimed', () => { query: { bool: { must: [ + { + bool: { + must: [ + { + term: { + 'task.enabled': true, + }, + }, + ], + }, + }, // Either a task with idle status and runAt <= now or // status running or claiming with a retryAt <= now. { diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts index afdd9c5c18b33f..d477c9c643a492 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts @@ -72,6 +72,18 @@ export const InactiveTasks: MustNotCondition = { }, }; +export const EnabledTask: MustCondition = { + bool: { + must: [ + { + term: { + 'task.enabled': true, + }, + }, + ], + }, +}; + export const RunningOrClaimingTaskWithExpiredRetryAt: MustCondition = { bool: { must: [ diff --git a/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts b/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts index 67175c86370d73..a23c29a5044f30 100644 --- a/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts +++ b/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts @@ -312,6 +312,17 @@ describe('TaskClaiming', () => { expect(query).toMatchObject({ bool: { must: [ + { + bool: { + must: [ + { + term: { + 'task.enabled': true, + }, + }, + ], + }, + }, { bool: { should: [ @@ -437,6 +448,17 @@ if (doc['task.runAt'].size()!=0) { organic: { bool: { must: [ + { + bool: { + must: [ + { + term: { + 'task.enabled': true, + }, + }, + ], + }, + }, { bool: { should: [ @@ -929,6 +951,17 @@ if (doc['task.runAt'].size()!=0) { expect(query).toMatchObject({ bool: { must: [ + { + bool: { + must: [ + { + term: { + 'task.enabled': true, + }, + }, + ], + }, + }, { bool: { should: [ diff --git a/x-pack/plugins/task_manager/server/queries/task_claiming.ts b/x-pack/plugins/task_manager/server/queries/task_claiming.ts index f15639661e5d0c..7226a558549881 100644 --- a/x-pack/plugins/task_manager/server/queries/task_claiming.ts +++ b/x-pack/plugins/task_manager/server/queries/task_claiming.ts @@ -43,6 +43,7 @@ import { SortByRunAtAndRetryAt, tasksClaimedByOwner, tasksOfType, + EnabledTask, } from './mark_available_tasks_as_claimed'; import { TaskTypeDictionary } from '../task_type_dictionary'; import { @@ -384,6 +385,8 @@ export class TaskClaiming { : 'taskTypesToSkip' ); const queryForScheduledTasks = mustBeAllOf( + // Task must be enabled + EnabledTask, // Either a task with idle status and runAt <= now or // status running or claiming with a retryAt <= now. shouldBeOneOf(IdleTaskWithExpiredRunAt, RunningOrClaimingTaskWithExpiredRetryAt) diff --git a/x-pack/plugins/task_manager/server/saved_objects/mappings.json b/x-pack/plugins/task_manager/server/saved_objects/mappings.json index d046a9266cce52..00129ac1bcdd4f 100644 --- a/x-pack/plugins/task_manager/server/saved_objects/mappings.json +++ b/x-pack/plugins/task_manager/server/saved_objects/mappings.json @@ -16,6 +16,9 @@ "retryAt": { "type": "date" }, + "enabled": { + "type": "boolean" + }, "schedule": { "properties": { "interval": { diff --git a/x-pack/plugins/task_manager/server/saved_objects/migrations.test.ts b/x-pack/plugins/task_manager/server/saved_objects/migrations.test.ts index a59fb077dbdeb1..fe8cc3f81eced3 100644 --- a/x-pack/plugins/task_manager/server/saved_objects/migrations.test.ts +++ b/x-pack/plugins/task_manager/server/saved_objects/migrations.test.ts @@ -226,6 +226,47 @@ describe('successful migrations', () => { expect(migration820(taskInstance, migrationContext)).toEqual(taskInstance); }); }); + + describe('8.5.0', () => { + test('adds enabled: true to tasks that are running, claiming, or idle', () => { + const migration850 = getMigrations()['8.5.0']; + const activeTasks = [ + getMockData({ + status: 'running', + }), + getMockData({ + status: 'claiming', + }), + getMockData({ + status: 'idle', + }), + ]; + activeTasks.forEach((task) => { + expect(migration850(task, migrationContext)).toEqual({ + ...task, + attributes: { + ...task.attributes, + enabled: true, + }, + }); + }); + }); + + test('does not modify tasks that are failed or unrecognized', () => { + const migration850 = getMigrations()['8.5.0']; + const inactiveTasks = [ + getMockData({ + status: 'failed', + }), + getMockData({ + status: 'unrecognized', + }), + ]; + inactiveTasks.forEach((task) => { + expect(migration850(task, migrationContext)).toEqual(task); + }); + }); + }); }); describe('handles errors during migrations', () => { diff --git a/x-pack/plugins/task_manager/server/saved_objects/migrations.ts b/x-pack/plugins/task_manager/server/saved_objects/migrations.ts index eb4ff6c1b0ecfc..a147a6bdabc6bc 100644 --- a/x-pack/plugins/task_manager/server/saved_objects/migrations.ts +++ b/x-pack/plugins/task_manager/server/saved_objects/migrations.ts @@ -42,6 +42,7 @@ export function getMigrations(): SavedObjectMigrationMap { pipeMigrations(resetAttemptsAndStatusForTheTasksWithoutSchedule, resetUnrecognizedStatus), '8.2.0' ), + '8.5.0': executeMigrationWithErrorHandling(pipeMigrations(addEnabledField), '8.5.0'), }; } @@ -193,3 +194,20 @@ function resetAttemptsAndStatusForTheTasksWithoutSchedule( return doc; } + +function addEnabledField(doc: SavedObjectUnsanitizedDoc<ConcreteTaskInstance>) { + if ( + doc.attributes.status === TaskStatus.Failed || + doc.attributes.status === TaskStatus.Unrecognized + ) { + return doc; + } + + return { + ...doc, + attributes: { + ...doc.attributes, + enabled: true, + }, + }; +} diff --git a/x-pack/plugins/task_manager/server/task.ts b/x-pack/plugins/task_manager/server/task.ts index 6d12a3f5984ca3..ebb957e54699a8 100644 --- a/x-pack/plugins/task_manager/server/task.ts +++ b/x-pack/plugins/task_manager/server/task.ts @@ -277,6 +277,11 @@ export interface TaskInstance { * The random uuid of the Kibana instance which claimed ownership of the task last */ ownerId?: string | null; + + /** + * Indicates whether the task is currently enabled. Disabled tasks will not be claimed. + */ + enabled?: boolean; } /** @@ -371,7 +376,10 @@ export interface ConcreteTaskInstance extends TaskInstance { /** * A task instance that has an id and is ready for storage. */ -export type EphemeralTask = Pick<ConcreteTaskInstance, 'taskType' | 'params' | 'state' | 'scope'>; +export type EphemeralTask = Pick< + ConcreteTaskInstance, + 'taskType' | 'params' | 'state' | 'scope' | 'enabled' +>; export type EphemeralTaskInstance = EphemeralTask & Pick<ConcreteTaskInstance, 'id' | 'scheduledAt' | 'startedAt' | 'runAt' | 'status' | 'ownerId'>; diff --git a/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts b/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts index f61bd762de4588..a9c58b1302f56a 100644 --- a/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts +++ b/x-pack/plugins/task_manager/server/task_running/task_runner.test.ts @@ -179,6 +179,7 @@ describe('TaskManagerRunner', () => { schedule: { interval: `${intervalMinutes}m`, }, + enabled: true, }, definitions: { bar: { @@ -198,6 +199,7 @@ describe('TaskManagerRunner', () => { expect(instance.retryAt!.getTime()).toEqual( instance.startedAt!.getTime() + intervalMinutes * 60 * 1000 ); + expect(instance.enabled).not.toBeDefined(); }); test('calculates retryAt by default timout when it exceeds the schedule of a recurring task', async () => { @@ -211,6 +213,7 @@ describe('TaskManagerRunner', () => { schedule: { interval: `${intervalSeconds}s`, }, + enabled: true, }, definitions: { bar: { @@ -228,6 +231,7 @@ describe('TaskManagerRunner', () => { const instance = store.update.mock.calls[0][0]; expect(instance.retryAt!.getTime()).toEqual(instance.startedAt!.getTime() + 5 * 60 * 1000); + expect(instance.enabled).not.toBeDefined(); }); test('calculates retryAt by timeout if it exceeds the schedule when running a recurring task', async () => { @@ -242,6 +246,7 @@ describe('TaskManagerRunner', () => { schedule: { interval: `${intervalSeconds}s`, }, + enabled: true, }, definitions: { bar: { @@ -262,6 +267,7 @@ describe('TaskManagerRunner', () => { expect(instance.retryAt!.getTime()).toEqual( instance.startedAt!.getTime() + timeoutMinutes * 60 * 1000 ); + expect(instance.enabled).not.toBeDefined(); }); test('sets startedAt, status, attempts and retryAt when claiming a task', async () => { @@ -271,6 +277,7 @@ describe('TaskManagerRunner', () => { const { runner, store } = await pendingStageSetup({ instance: { id, + enabled: true, attempts: initialAttempts, schedule: undefined, }, @@ -296,6 +303,7 @@ describe('TaskManagerRunner', () => { expect(instance.retryAt!.getTime()).toEqual( minutesFromNow((initialAttempts + 1) * 5).getTime() + timeoutMinutes * 60 * 1000 ); + expect(instance.enabled).not.toBeDefined(); }); test('uses getRetry (returning date) to set retryAt when defined', async () => { @@ -309,6 +317,7 @@ describe('TaskManagerRunner', () => { id, attempts: initialAttempts, schedule: undefined, + enabled: true, }, definitions: { bar: { @@ -331,6 +340,7 @@ describe('TaskManagerRunner', () => { expect(instance.retryAt!.getTime()).toEqual( new Date(nextRetry.getTime() + timeoutMinutes * 60 * 1000).getTime() ); + expect(instance.enabled).not.toBeDefined(); }); test('it returns false when markTaskAsRunning fails due to VERSION_CONFLICT_STATUS', async () => { @@ -539,6 +549,7 @@ describe('TaskManagerRunner', () => { id, attempts: initialAttempts, schedule: undefined, + enabled: true, }, definitions: { bar: { @@ -563,6 +574,7 @@ describe('TaskManagerRunner', () => { expect(instance.retryAt!.getTime()).toEqual( new Date(Date.now() + attemptDelay + timeoutDelay).getTime() ); + expect(instance.enabled).not.toBeDefined(); }); test('uses getRetry (returning false) to set retryAt when defined', async () => { @@ -575,6 +587,7 @@ describe('TaskManagerRunner', () => { id, attempts: initialAttempts, schedule: undefined, + enabled: true, }, definitions: { bar: { @@ -596,6 +609,7 @@ describe('TaskManagerRunner', () => { expect(instance.retryAt!).toBeNull(); expect(instance.status).toBe('running'); + expect(instance.enabled).not.toBeDefined(); }); test('bypasses getRetry (returning false) of a recurring task to set retryAt when defined', async () => { @@ -609,6 +623,7 @@ describe('TaskManagerRunner', () => { attempts: initialAttempts, schedule: { interval: '1m' }, startedAt: new Date(), + enabled: true, }, definitions: { bar: { @@ -630,6 +645,7 @@ describe('TaskManagerRunner', () => { const timeoutDelay = timeoutMinutes * 60 * 1000; expect(instance.retryAt!.getTime()).toEqual(new Date(Date.now() + timeoutDelay).getTime()); + expect(instance.enabled).not.toBeDefined(); }); describe('TaskEvents', () => { @@ -781,6 +797,7 @@ describe('TaskManagerRunner', () => { attempts: initialAttempts, params: { a: 'b' }, state: { hey: 'there' }, + enabled: true, }, definitions: { bar: { @@ -803,6 +820,7 @@ describe('TaskManagerRunner', () => { expect(instance.runAt.getTime()).toEqual(minutesFromNow(initialAttempts * 5).getTime()); expect(instance.params).toEqual({ a: 'b' }); expect(instance.state).toEqual({ hey: 'there' }); + expect(instance.enabled).not.toBeDefined(); }); test('reschedules tasks that have an schedule', async () => { @@ -811,6 +829,7 @@ describe('TaskManagerRunner', () => { schedule: { interval: '10m' }, status: TaskStatus.Running, startedAt: new Date(), + enabled: true, }, definitions: { bar: { @@ -831,6 +850,7 @@ describe('TaskManagerRunner', () => { expect(instance.runAt.getTime()).toBeGreaterThan(minutesFromNow(9).getTime()); expect(instance.runAt.getTime()).toBeLessThanOrEqual(minutesFromNow(10).getTime()); + expect(instance.enabled).not.toBeDefined(); }); test('expiration returns time after which timeout will have elapsed from start', async () => { @@ -951,6 +971,7 @@ describe('TaskManagerRunner', () => { schedule: { interval: '20m' }, status: TaskStatus.Running, startedAt: new Date(), + enabled: true, }, definitions: { bar: { @@ -968,6 +989,7 @@ describe('TaskManagerRunner', () => { const instance = store.update.mock.calls[0][0]; expect(instance.status).toBe('failed'); + expect(instance.enabled).not.toBeDefined(); expect(onTaskEvent).toHaveBeenCalledWith( withAnyTiming( @@ -1092,6 +1114,7 @@ describe('TaskManagerRunner', () => { instance: { id, attempts: initialAttempts, + enabled: true, }, definitions: { bar: { @@ -1113,6 +1136,7 @@ describe('TaskManagerRunner', () => { const instance = store.update.mock.calls[0][0]; expect(instance.runAt.getTime()).toEqual(nextRetry.getTime()); + expect(instance.enabled).not.toBeDefined(); }); test('uses getRetry function (returning true) on error when defined', async () => { @@ -1124,6 +1148,7 @@ describe('TaskManagerRunner', () => { instance: { id, attempts: initialAttempts, + enabled: true, }, definitions: { bar: { @@ -1146,6 +1171,7 @@ describe('TaskManagerRunner', () => { const expectedRunAt = new Date(Date.now() + initialAttempts * 5 * 60 * 1000); expect(instance.runAt.getTime()).toEqual(expectedRunAt.getTime()); + expect(instance.enabled).not.toBeDefined(); }); test('uses getRetry function (returning false) on error when defined', async () => { @@ -1157,6 +1183,7 @@ describe('TaskManagerRunner', () => { instance: { id, attempts: initialAttempts, + enabled: true, }, definitions: { bar: { @@ -1178,6 +1205,7 @@ describe('TaskManagerRunner', () => { const instance = store.update.mock.calls[0][0]; expect(instance.status).toBe('failed'); + expect(instance.enabled).not.toBeDefined(); }); test('bypasses getRetry function (returning false) on error of a recurring task', async () => { @@ -1191,6 +1219,7 @@ describe('TaskManagerRunner', () => { attempts: initialAttempts, schedule: { interval: '1m' }, startedAt: new Date(), + enabled: true, }, definitions: { bar: { @@ -1214,6 +1243,7 @@ describe('TaskManagerRunner', () => { const nextIntervalDelay = 60000; // 1m const expectedRunAt = new Date(Date.now() + nextIntervalDelay); expect(instance.runAt.getTime()).toEqual(expectedRunAt.getTime()); + expect(instance.enabled).not.toBeDefined(); }); test('Fails non-recurring task when maxAttempts reached', async () => { @@ -1224,6 +1254,7 @@ describe('TaskManagerRunner', () => { id, attempts: initialAttempts, schedule: undefined, + enabled: true, }, definitions: { bar: { @@ -1246,6 +1277,7 @@ describe('TaskManagerRunner', () => { expect(instance.status).toEqual('failed'); expect(instance.retryAt!).toBeNull(); expect(instance.runAt.getTime()).toBeLessThanOrEqual(Date.now()); + expect(instance.enabled).not.toBeDefined(); }); test(`Doesn't fail recurring tasks when maxAttempts reached`, async () => { @@ -1258,6 +1290,7 @@ describe('TaskManagerRunner', () => { attempts: initialAttempts, schedule: { interval: `${intervalSeconds}s` }, startedAt: new Date(), + enabled: true, }, definitions: { bar: { @@ -1281,6 +1314,7 @@ describe('TaskManagerRunner', () => { expect(instance.runAt.getTime()).toEqual( new Date(Date.now() + intervalSeconds * 1000).getTime() ); + expect(instance.enabled).not.toBeDefined(); }); describe('TaskEvents', () => { @@ -1450,6 +1484,7 @@ describe('TaskManagerRunner', () => { instance: { id, startedAt: new Date(), + enabled: true, }, definitions: { bar: { @@ -1468,6 +1503,7 @@ describe('TaskManagerRunner', () => { const instance = store.update.mock.calls[0][0]; expect(instance.status).toBe('failed'); + expect(instance.enabled).not.toBeDefined(); expect(onTaskEvent).toHaveBeenCalledWith( withAnyTiming( diff --git a/x-pack/plugins/task_manager/server/task_running/task_runner.ts b/x-pack/plugins/task_manager/server/task_running/task_runner.ts index 0b735d6b0ede60..a5865abc46bbe0 100644 --- a/x-pack/plugins/task_manager/server/task_running/task_runner.ts +++ b/x-pack/plugins/task_manager/server/task_running/task_runner.ts @@ -14,7 +14,7 @@ import apm from 'elastic-apm-node'; import uuid from 'uuid'; import { withSpan } from '@kbn/apm-utils'; -import { identity, defaults, flow } from 'lodash'; +import { identity, defaults, flow, omit } from 'lodash'; import { Logger, SavedObjectsErrorHelpers, ExecutionContextStart } from '@kbn/core/server'; import { UsageCounter } from '@kbn/usage-collection-plugin/server'; import { Middleware } from '../lib/middleware'; @@ -375,7 +375,7 @@ export class TaskManagerRunner implements TaskRunner { this.instance = asReadyToRun( (await this.bufferedTaskStore.update({ - ...taskInstance, + ...taskWithoutEnabled(taskInstance), status: TaskStatus.Running, startedAt: now, attempts, @@ -456,7 +456,7 @@ export class TaskManagerRunner implements TaskRunner { private async releaseClaimAndIncrementAttempts(): Promise<Result<ConcreteTaskInstance, Error>> { return promiseResult( this.bufferedTaskStore.update({ - ...this.instance.task, + ...taskWithoutEnabled(this.instance.task), status: TaskStatus.Idle, attempts: this.instance.task.attempts + 1, startedAt: null, @@ -549,7 +549,7 @@ export class TaskManagerRunner implements TaskRunner { retryAt: null, ownerId: null, }, - this.instance.task + taskWithoutEnabled(this.instance.task) ) ) ); @@ -677,6 +677,12 @@ function howManyMsUntilOwnershipClaimExpires(ownershipClaimedUntil: Date | null) return ownershipClaimedUntil ? ownershipClaimedUntil.getTime() - Date.now() : 0; } +// Omits "enabled" field from task updates so we don't overwrite any user +// initiated changes to "enabled" while the task was running +function taskWithoutEnabled(task: ConcreteTaskInstance): ConcreteTaskInstance { + return omit(task, 'enabled'); +} + // A type that extracts the Instance type out of TaskRunningStage // This helps us to better communicate to the developer what the expected "stage" // in a specific place in the code might be diff --git a/x-pack/plugins/task_manager/server/task_scheduling.mock.ts b/x-pack/plugins/task_manager/server/task_scheduling.mock.ts index 15c8dc06c473a8..08f36661dde52c 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.mock.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.mock.ts @@ -9,6 +9,7 @@ import { TaskScheduling } from './task_scheduling'; const createTaskSchedulingMock = () => { return { + bulkEnableDisable: jest.fn(), ensureScheduled: jest.fn(), schedule: jest.fn(), runSoon: jest.fn(), diff --git a/x-pack/plugins/task_manager/server/task_scheduling.test.ts b/x-pack/plugins/task_manager/server/task_scheduling.test.ts index a94394527a61d0..071b0147e19b24 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.test.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.test.ts @@ -70,6 +70,26 @@ describe('TaskScheduling', () => { id: undefined, schedule: undefined, traceparent: 'parent', + enabled: true, + }); + }); + + test('allows scheduling tasks that are disabled', async () => { + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + const task = { + taskType: 'foo', + enabled: false, + params: {}, + state: {}, + }; + await taskScheduling.schedule(task); + expect(mockTaskStore.schedule).toHaveBeenCalled(); + expect(mockTaskStore.schedule).toHaveBeenCalledWith({ + ...task, + id: undefined, + schedule: undefined, + traceparent: 'parent', + enabled: false, }); }); @@ -125,6 +145,133 @@ describe('TaskScheduling', () => { }); }); + describe('bulkEnableDisable', () => { + const id = '01ddff11-e88a-4d13-bc4e-256164e755e2'; + beforeEach(() => { + mockTaskStore.bulkUpdate.mockImplementation(() => + Promise.resolve([{ tag: 'ok', value: mockTask() }]) + ); + }); + + test('should search for tasks by ids enabled = true when disabling', async () => { + mockTaskStore.fetch.mockResolvedValue({ docs: [] }); + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + + await taskScheduling.bulkEnableDisable([id], false); + + expect(mockTaskStore.fetch).toHaveBeenCalledTimes(1); + expect(mockTaskStore.fetch).toHaveBeenCalledWith({ + query: { + bool: { + must: [ + { + terms: { + _id: [`task:${id}`], + }, + }, + { + term: { + 'task.enabled': true, + }, + }, + ], + }, + }, + size: 100, + }); + }); + + test('should search for tasks by ids enabled = false when enabling', async () => { + mockTaskStore.fetch.mockResolvedValue({ docs: [] }); + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + + await taskScheduling.bulkEnableDisable([id], true); + + expect(mockTaskStore.fetch).toHaveBeenCalledTimes(1); + expect(mockTaskStore.fetch).toHaveBeenCalledWith({ + query: { + bool: { + must: [ + { + terms: { + _id: [`task:${id}`], + }, + }, + { + term: { + 'task.enabled': false, + }, + }, + ], + }, + }, + size: 100, + }); + }); + + test('should split search on chunks when input ids array too large', async () => { + mockTaskStore.fetch.mockResolvedValue({ docs: [] }); + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + + await taskScheduling.bulkEnableDisable(Array.from({ length: 1250 }), false); + + expect(mockTaskStore.fetch).toHaveBeenCalledTimes(13); + }); + + test('should transform response into correct format', async () => { + const successfulTask = mockTask({ + id: 'task-1', + enabled: false, + schedule: { interval: '1h' }, + }); + const failedTask = mockTask({ id: 'task-2', enabled: true, schedule: { interval: '1h' } }); + mockTaskStore.bulkUpdate.mockImplementation(() => + Promise.resolve([ + { tag: 'ok', value: successfulTask }, + { tag: 'err', error: { entity: failedTask, error: new Error('fail') } }, + ]) + ); + mockTaskStore.fetch.mockResolvedValue({ docs: [successfulTask, failedTask] }); + + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + const result = await taskScheduling.bulkEnableDisable( + [successfulTask.id, failedTask.id], + false + ); + + expect(result).toEqual({ + tasks: [successfulTask], + errors: [{ task: failedTask, error: new Error('fail') }], + }); + }); + + test('should not disable task if it is already disabled', async () => { + const task = mockTask({ id, enabled: false, schedule: { interval: '3h' } }); + + mockTaskStore.fetch.mockResolvedValue({ docs: [task] }); + + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + await taskScheduling.bulkEnableDisable([id], false); + + const bulkUpdatePayload = mockTaskStore.bulkUpdate.mock.calls[0][0]; + + expect(bulkUpdatePayload).toHaveLength(0); + }); + + test('should not enable task if it is already enabled', async () => { + const task = mockTask({ id, enabled: true, schedule: { interval: '3h' } }); + + mockTaskStore.fetch.mockResolvedValue({ docs: [task] }); + + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + await taskScheduling.bulkEnableDisable([id], true); + + const bulkUpdatePayload = mockTaskStore.bulkUpdate.mock.calls[0][0]; + + expect(bulkUpdatePayload).toHaveLength(0); + }); + }); + describe('bulkUpdateSchedules', () => { const id = '01ddff11-e88a-4d13-bc4e-256164e755e2'; beforeEach(() => { @@ -258,6 +405,7 @@ describe('TaskScheduling', () => { expect(bulkUpdatePayload[0].runAt.getTime()).toBeLessThanOrEqual(Date.now()); }); }); + describe('runSoon', () => { test('resolves when the task update succeeds', async () => { const id = '01ddff11-e88a-4d13-bc4e-256164e755e2'; @@ -513,6 +661,40 @@ describe('TaskScheduling', () => { id: undefined, schedule: undefined, traceparent: 'parent', + enabled: true, + }, + ]); + }); + + test('allows scheduling tasks that are disabled', async () => { + const taskScheduling = new TaskScheduling(taskSchedulingOpts); + const task1 = { + taskType: 'foo', + params: {}, + state: {}, + }; + const task2 = { + taskType: 'foo', + params: {}, + state: {}, + enabled: false, + }; + await taskScheduling.bulkSchedule([task1, task2]); + expect(mockTaskStore.bulkSchedule).toHaveBeenCalled(); + expect(mockTaskStore.bulkSchedule).toHaveBeenCalledWith([ + { + ...task1, + id: undefined, + schedule: undefined, + traceparent: 'parent', + enabled: true, + }, + { + ...task2, + id: undefined, + schedule: undefined, + traceparent: 'parent', + enabled: false, }, ]); }); @@ -546,6 +728,7 @@ function mockTask(overrides: Partial<ConcreteTaskInstance> = {}): ConcreteTaskIn taskType: 'foo', schedule: undefined, attempts: 0, + enabled: true, status: TaskStatus.Claiming, params: { hello: 'world' }, state: { baby: 'Henhen' }, diff --git a/x-pack/plugins/task_manager/server/task_scheduling.ts b/x-pack/plugins/task_manager/server/task_scheduling.ts index 9434ba4fba0c31..8cd3330052cf46 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.ts @@ -48,7 +48,7 @@ import { EphemeralTaskLifecycle } from './ephemeral_task_lifecycle'; import { EphemeralTaskRejectedDueToCapacityError } from './task_running'; const VERSION_CONFLICT_STATUS = 409; - +const BULK_ACTION_SIZE = 100; export interface TaskSchedulingOpts { logger: Logger; taskStore: TaskStore; @@ -61,7 +61,7 @@ export interface TaskSchedulingOpts { /** * return type of TaskScheduling.bulkUpdateSchedules method */ -export interface BulkUpdateSchedulesResult { +export interface BulkUpdateTaskResult { /** * list of successfully updated tasks */ @@ -126,6 +126,7 @@ export class TaskScheduling { return await this.store.schedule({ ...modifiedTask, traceparent: traceparent || '', + enabled: modifiedTask.enabled ?? true, }); } @@ -149,13 +150,72 @@ export class TaskScheduling { ...options, taskInstance: ensureDeprecatedFieldsAreCorrected(taskInstance, this.logger), }); - return { ...modifiedTask, traceparent: traceparent || '' }; + return { + ...modifiedTask, + traceparent: traceparent || '', + enabled: modifiedTask.enabled ?? true, + }; }) ); return await this.store.bulkSchedule(modifiedTasks); } + public async bulkEnableDisable( + taskIds: string[], + enabled: boolean + ): Promise<BulkUpdateTaskResult> { + const tasks = await pMap( + chunk(taskIds, BULK_ACTION_SIZE), + async (taskIdsChunk) => + this.store.fetch({ + query: { + bool: { + must: [ + { + terms: { + _id: taskIdsChunk.map((taskId) => `task:${taskId}`), + }, + }, + { + term: { + 'task.enabled': !enabled, + }, + }, + ], + }, + }, + size: BULK_ACTION_SIZE, + }), + { concurrency: 10 } + ); + + const updatedTasks = tasks + .flatMap(({ docs }) => docs) + .reduce<ConcreteTaskInstance[]>((acc, task) => { + // if task is not enabled, no need to update it + if (enabled === task.enabled) { + return acc; + } + + acc.push({ ...task, enabled }); + return acc; + }, []); + + return (await this.store.bulkUpdate(updatedTasks)).reduce<BulkUpdateTaskResult>( + (acc, task) => { + if (task.tag === 'ok') { + acc.tasks.push(task.value); + } else { + acc.errors.push({ error: task.error.error, task: task.error.entity }); + } + + return acc; + }, + { tasks: [], errors: [] } + ); + } + /** * Bulk updates schedules for tasks by ids. * Only tasks with `idle` status will be updated, as for the tasks which have `running` status, @@ -163,14 +223,14 @@ export class TaskScheduling { * * @param {string[]} taskIds - list of task ids * @param {IntervalSchedule} schedule - new schedule - * @returns {Promise<BulkUpdateSchedulesResult>} + * @returns {Promise<BulkUpdateTaskResult>} */ public async bulkUpdateSchedules( taskIds: string[], schedule: IntervalSchedule - ): Promise<BulkUpdateSchedulesResult> { + ): Promise<BulkUpdateTaskResult> { const tasks = await pMap( - chunk(taskIds, 100), + chunk(taskIds, BULK_ACTION_SIZE), async (taskIdsChunk) => this.store.fetch({ query: mustBeAllOf( @@ -185,7 +245,7 @@ export class TaskScheduling { }, } ), - size: 100, + size: BULK_ACTION_SIZE, }), { concurrency: 10 } ); @@ -211,7 +271,7 @@ export class TaskScheduling { return acc; }, []); - return (await this.store.bulkUpdate(updatedTasks)).reduce<BulkUpdateSchedulesResult>( + return (await this.store.bulkUpdate(updatedTasks)).reduce<BulkUpdateTaskResult>( (acc, task) => { if (task.tag === 'ok') { acc.tasks.push(task.value); @@ -226,7 +286,7 @@ export class TaskScheduling { } /** - * Run task. + * Run task. * * @param taskId - The task being scheduled. * @returns {Promise<RunSoonResult>} diff --git a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts index d8b1397edbd75e..19d62bdd0682a1 100644 --- a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts +++ b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts @@ -20,6 +20,48 @@ export class TaskManagerUtils { this.retry = retry; } + async waitForDisabled(id: string, taskRunAtFilter: Date) { + return await this.retry.try(async () => { + const searchResult = await this.es.search({ + index: '.kibana_task_manager', + body: { + query: { + bool: { + must: [ + { + term: { + 'task.id': `task:${id}`, + }, + }, + { + terms: { + 'task.scope': ['actions', 'alerting'], + }, + }, + { + range: { + 'task.scheduledAt': { + gte: taskRunAtFilter.getTime().toString(), + }, + }, + }, + { + term: { + 'task.enabled': true, + }, + }, + ], + }, + }, + }, + }); + // @ts-expect-error + if (searchResult.hits.total.value) { + // @ts-expect-error + throw new Error(`Expected 0 tasks but received ${searchResult.hits.total.value}`); + } + }); + } async waitForEmpty(taskRunAtFilter: Date) { return await this.retry.try(async () => { const searchResult = await this.es.search({ diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts index e601c6ee15ec73..f775b3607fadee 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts @@ -137,6 +137,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { spaceId: space.id, consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); // Ensure AAD isn't broken await checkAAD({ supertest, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts index 842a00366945a0..2f452a54927b99 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts @@ -16,6 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, + TaskManagerDoc, } from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export @@ -30,11 +31,12 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte after(() => objectRemover.removeAll()); - async function getScheduledTask(id: string) { - return await es.get({ + async function getScheduledTask(id: string): Promise<TaskManagerDoc> { + const scheduledTask = await es.get<TaskManagerDoc>({ id: `task:${id}`, index: '.kibana_task_manager', }); + return scheduledTask._source!; } for (const scenario of UserAtSpaceScenarios) { @@ -88,8 +90,16 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte ), statusCode: 403, }); - // Ensure task still exists - await getScheduledTask(createdAlert.scheduled_task_id); + // Ensure task still exists and is still enabled + const taskRecord1 = await getScheduledTask(createdAlert.scheduled_task_id); + expect(taskRecord1.type).to.eql('task'); + expect(taskRecord1.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord1.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: space.id, + consumer: 'alertsFixture', + }); + expect(taskRecord1.task.enabled).to.eql(true); break; case 'space_1_all_alerts_none_actions at space1': case 'superuser at space1': @@ -97,12 +107,17 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte case 'space_1_all_with_restricted_fixture at space1': expect(response.statusCode).to.eql(204); expect(response.body).to.eql(''); - try { - await getScheduledTask(createdAlert.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } + + // task should still exist but be disabled + const taskRecord2 = await getScheduledTask(createdAlert.scheduled_task_id); + expect(taskRecord2.type).to.eql('task'); + expect(taskRecord2.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord2.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: space.id, + consumer: 'alertsFixture', + }); + expect(taskRecord2.task.enabled).to.eql(false); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -153,12 +168,17 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte case 'space_1_all_with_restricted_fixture at space1': expect(response.statusCode).to.eql(204); expect(response.body).to.eql(''); - try { - await getScheduledTask(createdAlert.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } + + // task should still exist but be disabled + const taskRecord = await getScheduledTask(createdAlert.scheduled_task_id); + expect(taskRecord.type).to.eql('task'); + expect(taskRecord.task.taskType).to.eql('alerting:test.restricted-noop'); + expect(JSON.parse(taskRecord.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: space.id, + consumer: 'alertsRestrictedFixture', + }); + expect(taskRecord.task.enabled).to.eql(false); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -213,12 +233,16 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte case 'space_1_all_with_restricted_fixture at space1': expect(response.statusCode).to.eql(204); expect(response.body).to.eql(''); - try { - await getScheduledTask(createdAlert.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } + // task should still exist but be disabled + const taskRecord = await getScheduledTask(createdAlert.scheduled_task_id); + expect(taskRecord.type).to.eql('task'); + expect(taskRecord.task.taskType).to.eql('alerting:test.unrestricted-noop'); + expect(JSON.parse(taskRecord.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: space.id, + consumer: 'alertsFixture', + }); + expect(taskRecord.task.enabled).to.eql(false); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -269,12 +293,16 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte case 'space_1_all_with_restricted_fixture at space1': expect(response.statusCode).to.eql(204); expect(response.body).to.eql(''); - try { - await getScheduledTask(createdAlert.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } + // task should still exist but be disabled + const taskRecord = await getScheduledTask(createdAlert.scheduled_task_id); + expect(taskRecord.type).to.eql('task'); + expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: space.id, + consumer: 'alerts', + }); + expect(taskRecord.task.enabled).to.eql(false); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -319,8 +347,16 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte ), statusCode: 403, }); - // Ensure task still exists - await getScheduledTask(createdAlert.scheduled_task_id); + // Ensure task still exists and is still enabled + const taskRecord1 = await getScheduledTask(createdAlert.scheduled_task_id); + expect(taskRecord1.type).to.eql('task'); + expect(taskRecord1.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord1.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: space.id, + consumer: 'alertsFixture', + }); + expect(taskRecord1.task.enabled).to.eql(true); break; case 'superuser at space1': case 'space_1_all at space1': @@ -328,12 +364,16 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte case 'space_1_all_with_restricted_fixture at space1': expect(response.statusCode).to.eql(204); expect(response.body).to.eql(''); - try { - await getScheduledTask(createdAlert.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } + // task should still exist but be disabled + const taskRecord2 = await getScheduledTask(createdAlert.scheduled_task_id); + expect(taskRecord2.type).to.eql('task'); + expect(taskRecord2.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord2.task.params)).to.eql({ + alertId: createdAlert.id, + spaceId: space.id, + consumer: 'alertsFixture', + }); + expect(taskRecord2.task.enabled).to.eql(false); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts index 0aba468174cffd..73842073a542b5 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts @@ -129,6 +129,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex spaceId: space.id, consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -360,6 +361,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex spaceId: space.id, consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); // Ensure AAD isn't broken await checkAAD({ supertest, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts index 19c10bddbd7b1c..c20e41067b0101 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts @@ -34,7 +34,7 @@ export default function alertTests({ getService }: FtrProviderContext) { const esTestIndexTool = new ESTestIndexTool(es, retry); const taskManagerUtils = new TaskManagerUtils(es, retry); - describe('alerts', () => { + describe('alerts test me', () => { const authorizationIndex = '.kibana-test-authorization'; const objectRemover = new ObjectRemover(supertest); @@ -122,7 +122,7 @@ export default function alertTests({ getService }: FtrProviderContext) { const alertId = response.body.id; await alertUtils.disable(alertId); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(alertId, testStart); // Ensure only 1 alert executed with proper params const alertSearchResult = await esTestIndexTool.search( @@ -274,7 +274,7 @@ instanceStateValue: true const alertId = response.body.id; await alertUtils.disable(alertId); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(alertId, testStart); // Ensure only 1 alert executed with proper params const alertSearchResult = await esTestIndexTool.search( @@ -634,7 +634,7 @@ instanceStateValue: true // Wait for test.authorization to index a document before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('alert:test.authorization', reference); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure only 1 document exists with proper params searchResult = await esTestIndexTool.search('alert:test.authorization', reference); @@ -665,7 +665,7 @@ instanceStateValue: true // Wait for test.authorization to index a document before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('alert:test.authorization', reference); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure only 1 document exists with proper params searchResult = await esTestIndexTool.search('alert:test.authorization', reference); @@ -751,7 +751,7 @@ instanceStateValue: true // Ensure test.authorization indexed 1 document before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('action:test.authorization', reference); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure only 1 document with proper params exists searchResult = await esTestIndexTool.search('action:test.authorization', reference); @@ -790,7 +790,7 @@ instanceStateValue: true // Ensure test.authorization indexed 1 document before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('action:test.authorization', reference); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure only 1 document with proper params exists searchResult = await esTestIndexTool.search('action:test.authorization', reference); @@ -853,7 +853,7 @@ instanceStateValue: true // Wait until alerts scheduled actions 3 times before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('alert:test.always-firing', reference, 3); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure actions only executed once const searchResult = await esTestIndexTool.search( @@ -933,7 +933,7 @@ instanceStateValue: true // Wait for actions to execute twice before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('action:test.index-record', reference, 2); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure only 2 actions with proper params exists const searchResult = await esTestIndexTool.search( @@ -1009,7 +1009,7 @@ instanceStateValue: true // Wait for actions to execute twice before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('action:test.index-record', reference, 2); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure only 2 actions with proper params exists const searchResult = await esTestIndexTool.search( @@ -1074,7 +1074,7 @@ instanceStateValue: true // Actions should execute twice before widning things down await esTestIndexTool.waitForDocs('action:test.index-record', reference, 2); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Ensure only 2 actions are executed const searchResult = await esTestIndexTool.search( @@ -1133,7 +1133,7 @@ instanceStateValue: true // execution once before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('alert:test.always-firing', reference, 2); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Should not have executed any action const executedActionsResult = await esTestIndexTool.search( @@ -1192,7 +1192,7 @@ instanceStateValue: true // once before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('alert:test.always-firing', reference, 2); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Should not have executed any action const executedActionsResult = await esTestIndexTool.search( @@ -1252,7 +1252,7 @@ instanceStateValue: true // Ensure actions are executed once before disabling the alert and waiting for tasks to finish await esTestIndexTool.waitForDocs('action:test.index-record', reference, 1); await alertUtils.disable(response.body.id); - await taskManagerUtils.waitForEmpty(testStart); + await taskManagerUtils.waitForDisabled(response.body.id, testStart); // Should have one document indexed by the action const searchResult = await esTestIndexTool.search( diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts index 143d845d074c4f..7860bf15dc8e53 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts @@ -108,6 +108,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { spaceId: Spaces.space1.id, consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); // Ensure AAD isn't broken await checkAAD({ supertest, @@ -498,6 +499,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { spaceId: Spaces.space1.id, consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); // Ensure AAD isn't broken await checkAAD({ supertest, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts index 6df7f4b3f6de8e..feec6431ee3cf9 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts @@ -15,6 +15,7 @@ import { getTestRuleData, ObjectRemover, getEventLog, + TaskManagerDoc, } from '../../../common/lib'; import { validateEvent } from './event_log'; @@ -31,11 +32,12 @@ export default function createDisableRuleTests({ getService }: FtrProviderContex after(() => objectRemover.removeAll()); - async function getScheduledTask(id: string) { - return await es.get({ + async function getScheduledTask(id: string): Promise<TaskManagerDoc> { + const scheduledTask = await es.get<TaskManagerDoc>({ id: `task:${id}`, index: '.kibana_task_manager', }); + return scheduledTask._source!; } it('should handle disable rule request appropriately', async () => { @@ -48,12 +50,16 @@ export default function createDisableRuleTests({ getService }: FtrProviderContex await ruleUtils.disable(createdRule.id); - try { - await getScheduledTask(createdRule.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } + // task doc should still exist but be disabled + const taskRecord = await getScheduledTask(createdRule.scheduled_task_id); + expect(taskRecord.type).to.eql('task'); + expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord.task.params)).to.eql({ + alertId: createdRule.id, + spaceId: Spaces.space1.id, + consumer: 'alertsFixture', + }); + expect(taskRecord.task.enabled).to.eql(false); // Ensure AAD isn't broken await checkAAD({ @@ -188,12 +194,16 @@ export default function createDisableRuleTests({ getService }: FtrProviderContex .set('kbn-xsrf', 'foo') .expect(204); - try { - await getScheduledTask(createdRule.scheduled_task_id); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } + // task doc should still exist but be disabled + const taskRecord = await getScheduledTask(createdRule.scheduled_task_id); + expect(taskRecord.type).to.eql('task'); + expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); + expect(JSON.parse(taskRecord.task.params)).to.eql({ + alertId: createdRule.id, + spaceId: Spaces.space1.id, + consumer: 'alertsFixture', + }); + expect(taskRecord.task.enabled).to.eql(false); // Ensure AAD isn't broken await checkAAD({ diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts index 59ae5efcba1919..d8dec2a486298b 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts @@ -59,6 +59,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex spaceId: Spaces.space1.id, consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); // Ensure AAD isn't broken await checkAAD({ @@ -111,6 +112,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex spaceId: Spaces.space1.id, consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); // Ensure AAD isn't broken await checkAAD({ diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/scheduled_task_id.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/scheduled_task_id.ts index 607166203e35ff..d008421381b14e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/scheduled_task_id.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/scheduled_task_id.ts @@ -109,6 +109,7 @@ export default function createScheduledTaskIdTests({ getService }: FtrProviderCo spaceId: 'default', consumer: 'alertsFixture', }); + expect(taskRecord.task.enabled).to.eql(true); }); }); } diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts index 04f34ab50a1331..232db750d54259 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts @@ -136,5 +136,59 @@ export default function createGetTests({ getService }: FtrProviderContext) { expect(response.body._source?.task.taskType).to.eql(`sampleTaskRemovedType`); expect(response.body._source?.task.status).to.eql(`unrecognized`); }); + + it('8.5.0 migrates active tasks to set enabled to true', async () => { + const response = await es.search<{ task: ConcreteTaskInstance }>( + { + index: '.kibana_task_manager', + size: 100, + body: { + query: { + match_all: {}, + }, + }, + }, + { + meta: true, + } + ); + expect(response.statusCode).to.eql(200); + const tasks = response.body.hits.hits; + tasks + .filter( + (task) => + task._source?.task.status !== 'failed' && task._source?.task.status !== 'unrecognized' + ) + .forEach((task) => { + expect(task._source?.task.enabled).to.eql(true); + }); + }); + + it('8.5.0 does not migrates failed and unrecognized', async () => { + const response = await es.search<{ task: ConcreteTaskInstance }>( + { + index: '.kibana_task_manager', + size: 100, + body: { + query: { + match_all: {}, + }, + }, + }, + { + meta: true, + } + ); + expect(response.statusCode).to.eql(200); + const tasks = response.body.hits.hits; + tasks + .filter( + (task) => + task._source?.task.status === 'failed' || task._source?.task.status === 'unrecognized' + ) + .forEach((task) => { + expect(task._source?.task.enabled).to.be(undefined); + }); + }); }); } diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts index cf720be74143ac..56477f0e6edf0f 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts @@ -11,7 +11,7 @@ import expect from '@kbn/expect'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import TaskManagerMapping from '@kbn/task-manager-plugin/server/saved_objects/mappings.json'; import { DEFAULT_POLL_INTERVAL } from '@kbn/task-manager-plugin/server/config'; -import { ConcreteTaskInstance, BulkUpdateSchedulesResult } from '@kbn/task-manager-plugin/server'; +import { ConcreteTaskInstance, BulkUpdateTaskResult } from '@kbn/task-manager-plugin/server'; import { FtrProviderContext } from '../../ftr_provider_context'; const { @@ -184,7 +184,7 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ taskIds, schedule }) .expect(200) - .then((response: { body: BulkUpdateSchedulesResult }) => response.body); + .then((response: { body: BulkUpdateTaskResult }) => response.body); } // TODO: Add this back in with https://github.com/elastic/kibana/issues/106139 From 38e74d7ee6f1089c7c4857b3ad320849ea782415 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Mon, 12 Sep 2022 15:40:20 +0200 Subject: [PATCH 060/144] [Fleet] moving action batching to async (#138870) * moving action batching to async * created new api for action status * fix types * fix types * added time measurement * added action status component, refactored reassign logic * refactored retry task to be reusable by other actions * refactored action runner to class * changed bulk update tags * build fixes * fix checks * passing retry options * fixed action status * improvements to action status api * improvements to action status api * removed timed out status * simplified code around retry tasks * added missing unenroll params * fix checks * increased upgrade action expiration to 2h for immediately * moved getActionStatusHandler to handlers, using its own response type * capturing failures with error message in a new .fleet-actions-status index * renamed status index so it doesn't get the same alias as .fleet-actions * cleaned up action and retry params * refactored to simplify passing params * added script to generate agent docs, fixed bugs * renamed action_status response props * small cleanup * refactor, cleanup * added tests * fixed tests * upgrade api test * renamed CurrentAction to ActionStatus model object * moved out action status UI and .fleet-action-status changes to simplify the pr * fixed toast message for single agent actions * added comments * fixed conflict resolution * reverted refreshAgents change * review comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../plugins/fleet/common/constants/routes.ts | 1 + .../plugins/fleet/common/services/routes.ts | 1 + .../fleet/common/types/models/agent.ts | 21 +- .../fleet/common/types/rest_spec/agent.ts | 6 +- x-pack/plugins/fleet/kibana.json | 2 +- .../agent_reassign_policy_modal/index.tsx | 9 +- .../components/agent_unenroll_modal/index.tsx | 13 +- .../components/agent_upgrade_modal/index.tsx | 12 +- .../fleet/public/hooks/use_request/agents.ts | 8 + x-pack/plugins/fleet/public/types/index.ts | 1 + .../scripts/create_agents/create_agents.ts | 143 ++++++++ .../fleet/scripts/create_agents/index.js | 17 + x-pack/plugins/fleet/server/mocks/index.ts | 1 + x-pack/plugins/fleet/server/plugin.ts | 12 + .../routes/agent/actions_handlers.test.ts | 1 + .../fleet/server/routes/agent/handlers.ts | 20 +- .../fleet/server/routes/agent/index.ts | 15 + .../server/routes/agent/unenroll_handler.ts | 2 +- .../server/routes/agent/upgrade_handler.ts | 2 +- .../server/services/agents/action_runner.ts | 188 ++++++++++ .../server/services/agents/action_status.ts | 142 ++++++++ .../fleet/server/services/agents/actions.ts | 30 ++ .../services/agents/bulk_actions_resolver.ts | 161 +++++++++ .../fleet/server/services/agents/crud.test.ts | 49 +-- .../fleet/server/services/agents/crud.ts | 51 --- .../services/agents/current_upgrades.ts | 150 ++++++++ .../fleet/server/services/agents/index.ts | 3 + .../fleet/server/services/agents/reassign.ts | 120 ++----- .../services/agents/reassign_action_runner.ts | 108 ++++++ .../server/services/agents/unenroll.test.ts | 3 +- .../fleet/server/services/agents/unenroll.ts | 129 ++----- .../services/agents/unenroll_action_runner.ts | 122 +++++++ .../services/agents/update_agent_tags.test.ts | 39 +++ .../services/agents/update_agent_tags.ts | 106 ++---- .../agents/update_agent_tags_action_runner.ts | 91 +++++ .../fleet/server/services/agents/upgrade.ts | 326 ++---------------- .../services/agents/upgrade_action_runner.ts | 180 ++++++++++ .../fleet/server/services/app_context.ts | 8 + x-pack/plugins/fleet/server/types/index.tsx | 1 + .../apis/agents/reassign.ts | 42 ++- .../apis/agents/unenroll.ts | 36 +- .../apis/agents/update_agent_tags.ts | 26 +- .../apis/agents/upgrade.ts | 49 ++- 43 files changed, 1722 insertions(+), 725 deletions(-) create mode 100644 x-pack/plugins/fleet/scripts/create_agents/create_agents.ts create mode 100644 x-pack/plugins/fleet/scripts/create_agents/index.js create mode 100644 x-pack/plugins/fleet/server/services/agents/action_runner.ts create mode 100644 x-pack/plugins/fleet/server/services/agents/action_status.ts create mode 100644 x-pack/plugins/fleet/server/services/agents/bulk_actions_resolver.ts create mode 100644 x-pack/plugins/fleet/server/services/agents/current_upgrades.ts create mode 100644 x-pack/plugins/fleet/server/services/agents/reassign_action_runner.ts create mode 100644 x-pack/plugins/fleet/server/services/agents/unenroll_action_runner.ts create mode 100644 x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts create mode 100644 x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts diff --git a/x-pack/plugins/fleet/common/constants/routes.ts b/x-pack/plugins/fleet/common/constants/routes.ts index b415328a303d3c..fa9e074899163a 100644 --- a/x-pack/plugins/fleet/common/constants/routes.ts +++ b/x-pack/plugins/fleet/common/constants/routes.ts @@ -126,6 +126,7 @@ export const AGENT_API_ROUTES = { UPGRADE_PATTERN: `${API_ROOT}/agents/{agentId}/upgrade`, BULK_UPGRADE_PATTERN: `${API_ROOT}/agents/bulk_upgrade`, CURRENT_UPGRADES_PATTERN: `${API_ROOT}/agents/current_upgrades`, + ACTION_STATUS_PATTERN: `${API_ROOT}/agents/action_status`, LIST_TAGS_PATTERN: `${API_ROOT}/agents/tags`, }; diff --git a/x-pack/plugins/fleet/common/services/routes.ts b/x-pack/plugins/fleet/common/services/routes.ts index 323d7d1f8b3786..c2f76758c3d7bd 100644 --- a/x-pack/plugins/fleet/common/services/routes.ts +++ b/x-pack/plugins/fleet/common/services/routes.ts @@ -194,6 +194,7 @@ export const agentRouteService = { getUpgradePath: (agentId: string) => AGENT_API_ROUTES.UPGRADE_PATTERN.replace('{agentId}', agentId), getBulkUpgradePath: () => AGENT_API_ROUTES.BULK_UPGRADE_PATTERN, + getActionStatusPath: () => AGENT_API_ROUTES.ACTION_STATUS_PATTERN, getCurrentUpgradesPath: () => AGENT_API_ROUTES.CURRENT_UPGRADES_PATTERN, getCancelActionPath: (actionId: string) => AGENT_API_ROUTES.CANCEL_ACTIONS_PATTERN.replace('{actionId}', actionId), diff --git a/x-pack/plugins/fleet/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts index 9924413cb16bf4..7b92e6e779fd51 100644 --- a/x-pack/plugins/fleet/common/types/models/agent.ts +++ b/x-pack/plugins/fleet/common/types/models/agent.ts @@ -47,6 +47,7 @@ export interface NewAgentAction { start_time?: string; minimum_execution_duration?: number; source_uri?: string; + total?: number; } export interface AgentAction extends NewAgentAction { @@ -104,6 +105,22 @@ export interface CurrentUpgrade { startTime?: string; } +export interface ActionStatus { + actionId: string; + // how many agents are successfully included in action documents + nbAgentsActionCreated: number; + // how many agents acknowledged the action sucessfully (completed) + nbAgentsAck: number; + version: string; + startTime?: string; + type?: string; + // how many agents were actioned by the user + nbAgentsActioned: number; + status: 'complete' | 'expired' | 'cancelled' | 'failed' | 'in progress'; + errorMessage?: string; +} + +// Generated from FleetServer schema.json interface FleetServerAgentComponentUnit { id: string; type: 'input' | 'output'; @@ -122,8 +139,6 @@ interface FleetServerAgentComponent { units: FleetServerAgentComponentUnit[]; } -// Initially generated from FleetServer schema.json - /** * An Elastic Agent that has enrolled into Fleet */ @@ -309,5 +324,7 @@ export interface FleetServerAgentAction { data?: { [k: string]: unknown; }; + + total?: number; [k: string]: unknown; } diff --git a/x-pack/plugins/fleet/common/types/rest_spec/agent.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent.ts index dae156c8c83548..7050fcd3da3466 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/agent.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/agent.ts @@ -7,7 +7,7 @@ import type { SearchHit } from '@kbn/core/types/elasticsearch'; -import type { Agent, AgentAction, CurrentUpgrade, NewAgentAction } from '../models'; +import type { Agent, AgentAction, ActionStatus, CurrentUpgrade, NewAgentAction } from '../models'; import type { ListResult, ListWithKuery } from './common'; @@ -125,6 +125,7 @@ export interface PostBulkAgentReassignRequest { body: { policy_id: string; agents: string[] | string; + batchSize?: number; }; } @@ -205,6 +206,9 @@ export interface GetAgentIncomingDataResponse { export interface GetCurrentUpgradesResponse { items: CurrentUpgrade[]; } +export interface GetActionStatusResponse { + items: ActionStatus[]; +} export interface GetAvailableVersionsResponse { items: string[]; } diff --git a/x-pack/plugins/fleet/kibana.json b/x-pack/plugins/fleet/kibana.json index 462e68a0979622..6ab87283e0b26f 100644 --- a/x-pack/plugins/fleet/kibana.json +++ b/x-pack/plugins/fleet/kibana.json @@ -8,7 +8,7 @@ "server": true, "ui": true, "configPath": ["xpack", "fleet"], - "requiredPlugins": ["licensing", "data", "encryptedSavedObjects", "navigation", "customIntegrations", "share", "spaces", "security", "unifiedSearch", "savedObjectsTagging"], + "requiredPlugins": ["licensing", "data", "encryptedSavedObjects", "navigation", "customIntegrations", "share", "spaces", "security", "unifiedSearch", "savedObjectsTagging", "taskManager"], "optionalPlugins": ["features", "cloud", "usageCollection", "home", "globalSearch", "telemetry", "discover", "ingestPipelines"], "extraPublicDirs": ["common"], "requiredBundles": ["kibanaReact", "cloud", "esUiShared", "infra", "kibanaUtils", "usageCollection", "unifiedSearch"] diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx index aee476723f1a95..cae8b00fb6d3d1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx @@ -82,13 +82,20 @@ export const AgentReassignAgentPolicyModal: React.FunctionComponent<Props> = ({ throw res.error; } setIsSubmitting(false); + const hasCompleted = isSingleAgent || Object.keys(res.data ?? {}).length > 0; const successMessage = i18n.translate( 'xpack.fleet.agentReassignPolicy.successSingleNotificationTitle', { defaultMessage: 'Agent policy reassigned', } ); - notifications.toasts.addSuccess(successMessage); + const submittedMessage = i18n.translate( + 'xpack.fleet.agentReassignPolicy.submittedNotificationTitle', + { + defaultMessage: 'Agent policy reassign submitted', + } + ); + notifications.toasts.addSuccess(hasCompleted ? successMessage : submittedMessage); onClose(); } catch (error) { setIsSubmitting(false); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_unenroll_modal/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_unenroll_modal/index.tsx index 72b1e00c1ed02a..7c0c0136c3d099 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_unenroll_modal/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_unenroll_modal/index.tsx @@ -40,7 +40,7 @@ export const AgentUnenrollAgentModal: React.FunctionComponent<Props> = ({ async function onSubmit() { try { setIsSubmitting(true); - const { error } = isSingleAgent + const { error, data } = isSingleAgent ? await sendPostAgentUnenroll((agents[0] as Agent).id, { revoke: forceUnenroll, }) @@ -52,6 +52,13 @@ export const AgentUnenrollAgentModal: React.FunctionComponent<Props> = ({ throw error; } setIsSubmitting(false); + const hasCompleted = isSingleAgent || Object.keys(data ?? {}).length > 0; + const submittedMessage = i18n.translate( + 'xpack.fleet.unenrollAgents.submittedNotificationTitle', + { + defaultMessage: 'Agent(s) unenroll submitted', + } + ); if (forceUnenroll) { const successMessage = isSingleAgent ? i18n.translate('xpack.fleet.unenrollAgents.successForceSingleNotificationTitle', { @@ -60,7 +67,7 @@ export const AgentUnenrollAgentModal: React.FunctionComponent<Props> = ({ : i18n.translate('xpack.fleet.unenrollAgents.successForceMultiNotificationTitle', { defaultMessage: 'Agents unenrolled', }); - notifications.toasts.addSuccess(successMessage); + notifications.toasts.addSuccess(hasCompleted ? successMessage : submittedMessage); } else { const successMessage = isSingleAgent ? i18n.translate('xpack.fleet.unenrollAgents.successSingleNotificationTitle', { @@ -69,7 +76,7 @@ export const AgentUnenrollAgentModal: React.FunctionComponent<Props> = ({ : i18n.translate('xpack.fleet.unenrollAgents.successMultiNotificationTitle', { defaultMessage: 'Unenrolling agents', }); - notifications.toasts.addSuccess(successMessage); + notifications.toasts.addSuccess(hasCompleted ? successMessage : submittedMessage); } onClose(); } catch (error) { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_upgrade_modal/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_upgrade_modal/index.tsx index 07b284058fc7de..c60536961e01fe 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_upgrade_modal/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_upgrade_modal/index.tsx @@ -192,7 +192,17 @@ export const AgentUpgradeAgentModal: React.FunctionComponent<AgentUpgradeAgentMo ); setIsSubmitting(false); - if (isSingleAgent && counts.success === counts.total) { + const hasCompleted = isSingleAgent || Object.keys(data ?? {}).length > 0; + const submittedMessage = i18n.translate( + 'xpack.fleet.upgradeAgents.submittedNotificationTitle', + { + defaultMessage: 'Agent(s) upgrade submitted', + } + ); + + if (!hasCompleted) { + notifications.toasts.addSuccess(submittedMessage); + } else if (isSingleAgent && counts.success === counts.total) { notifications.toasts.addSuccess( i18n.translate('xpack.fleet.upgradeAgents.successSingleNotificationTitle', { defaultMessage: 'Upgrading {count} agent', diff --git a/x-pack/plugins/fleet/public/hooks/use_request/agents.ts b/x-pack/plugins/fleet/public/hooks/use_request/agents.ts index da082a1ff0d459..13f687e321e548 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/agents.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/agents.ts @@ -6,6 +6,7 @@ */ import type { + GetActionStatusResponse, GetAgentTagsResponse, PostBulkUpdateAgentTagsRequest, UpdateAgentRequest, @@ -195,6 +196,13 @@ export function sendPostBulkAgentUpgrade( }); } +export function sendGetActionStatus() { + return sendRequest<GetActionStatusResponse>({ + path: agentRouteService.getActionStatusPath(), + method: 'get', + }); +} + export function sendGetCurrentUpgrades() { return sendRequest<GetCurrentUpgradesResponse>({ path: agentRouteService.getCurrentUpgradesPath(), diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 72755e74d858f7..2438272503ac78 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -26,6 +26,7 @@ export type { DownloadSource, DataStream, Settings, + ActionStatus, CurrentUpgrade, GetFleetStatusResponse, GetAgentPoliciesRequest, diff --git a/x-pack/plugins/fleet/scripts/create_agents/create_agents.ts b/x-pack/plugins/fleet/scripts/create_agents/create_agents.ts new file mode 100644 index 00000000000000..31df24c70a5d4b --- /dev/null +++ b/x-pack/plugins/fleet/scripts/create_agents/create_agents.ts @@ -0,0 +1,143 @@ +/* + * 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 fetch from 'node-fetch'; +import { ToolingLog } from '@kbn/tooling-log'; +import uuid from 'uuid/v4'; + +const KIBANA_URL = 'http://localhost:5601'; +const KIBANA_USERNAME = 'elastic'; +const KIBANA_PASSWORD = 'changeme'; + +const ES_URL = 'http://localhost:9200'; +const ES_SUPERUSER = 'fleet_superuser'; +const ES_PASSWORD = 'password'; + +async function createAgentDocsBulk(policyId: string, count: number) { + const auth = 'Basic ' + Buffer.from(ES_SUPERUSER + ':' + ES_PASSWORD).toString('base64'); + const body = ( + '{ "index":{ } }\n' + + JSON.stringify({ + access_api_key_id: 'api-key-1', + active: true, + policy_id: policyId, + type: 'PERMANENT', + local_metadata: { + elastic: { + agent: { + snapshot: false, + upgradeable: true, + version: '8.2.0', + }, + }, + host: { hostname: uuid() }, + }, + user_provided_metadata: {}, + enrolled_at: new Date().toISOString(), + last_checkin: new Date().toISOString(), + tags: ['script_create_agents'], + }) + + '\n' + ).repeat(count); + const res = await fetch(`${ES_URL}/.fleet-agents/_bulk`, { + method: 'post', + body, + headers: { + Authorization: auth, + 'Content-Type': 'application/x-ndjson', + }, + }); + const data = await res.json(); + return data; +} + +async function createSuperUser() { + const auth = 'Basic ' + Buffer.from(KIBANA_USERNAME + ':' + KIBANA_PASSWORD).toString('base64'); + const roleRes = await fetch(`${ES_URL}/_security/role/${ES_SUPERUSER}`, { + method: 'post', + body: JSON.stringify({ + indices: [ + { + names: ['.fleet*'], + privileges: ['all'], + allow_restricted_indices: true, + }, + ], + }), + headers: { + Authorization: auth, + 'Content-Type': 'application/json', + }, + }); + const role = await roleRes.json(); + const userRes = await fetch(`${ES_URL}/_security/user/${ES_SUPERUSER}`, { + method: 'post', + body: JSON.stringify({ + password: ES_PASSWORD, + roles: ['superuser', ES_SUPERUSER], + }), + headers: { + Authorization: auth, + 'Content-Type': 'application/json', + }, + }); + const user = await userRes.json(); + return { role, user }; +} + +async function createAgentPolicy(id: string) { + const auth = 'Basic ' + Buffer.from(KIBANA_USERNAME + ':' + KIBANA_PASSWORD).toString('base64'); + const res = await fetch(`${KIBANA_URL}/api/fleet/agent_policies`, { + method: 'post', + body: JSON.stringify({ + id, + name: id, + namespace: 'default', + description: '', + monitoring_enabled: ['logs'], + data_output_id: 'fleet-default-output', + monitoring_output_id: 'fleet-default-output', + }), + headers: { + Authorization: auth, + 'Content-Type': 'application/json', + 'kbn-xsrf': 'kibana', + 'x-elastic-product-origin': 'fleet', + }, + }); + const data = await res.json(); + return data; +} + +/** + * Script to create large number of agent documents at once. + * This is helpful for testing agent bulk actions locally as the kibana async logic kicks in for >10k agents. + */ +export async function run() { + const logger = new ToolingLog({ + level: 'info', + writeTo: process.stdout, + }); + + logger.info('Creating agent policy'); + + const agentPolicyId = uuid(); + const agentPolicy = await createAgentPolicy(agentPolicyId); + logger.info(`Created agent policy ${agentPolicy.item.id}`); + + logger.info('Creating fleet superuser'); + const { role, user } = await createSuperUser(); + logger.info(`Created role ${ES_SUPERUSER}, created: ${role.role.created}`); + logger.info(`Created user ${ES_SUPERUSER}, created: ${user.created}`); + + logger.info('Creating agent documents'); + const count = 50000; + const agents = await createAgentDocsBulk(agentPolicyId, count); + logger.info( + `Created ${agents.items.length} agent docs, took ${agents.took}, errors: ${agents.errors}` + ); +} diff --git a/x-pack/plugins/fleet/scripts/create_agents/index.js b/x-pack/plugins/fleet/scripts/create_agents/index.js new file mode 100644 index 00000000000000..62614b67ea69bf --- /dev/null +++ b/x-pack/plugins/fleet/scripts/create_agents/index.js @@ -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. + */ + +require('../../../../../src/setup_node_env'); +require('./create_agents').run(); + +/* +Usage: + +cd x-pack/plugins/fleet +node scripts/create_agents/index.js + +*/ diff --git a/x-pack/plugins/fleet/server/mocks/index.ts b/x-pack/plugins/fleet/server/mocks/index.ts index a76988506cad21..f3f9e5b59d3c49 100644 --- a/x-pack/plugins/fleet/server/mocks/index.ts +++ b/x-pack/plugins/fleet/server/mocks/index.ts @@ -73,6 +73,7 @@ export const createAppContextStartContractMock = ( kibanaVersion: '8.99.0', // Fake version :) kibanaBranch: 'main', telemetryEventsSender: createMockTelemetryEventsSender(), + bulkActionsResolver: {} as any, }; }; diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 0cec7c92c62b1e..57e65664d59690 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -37,6 +37,10 @@ import type { } from '@kbn/encrypted-saved-objects-plugin/server'; import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import type { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server'; +import type { + TaskManagerSetupContract, + TaskManagerStartContract, +} from '@kbn/task-manager-plugin/server'; import type { CloudSetup } from '@kbn/cloud-plugin/server'; @@ -100,6 +104,7 @@ import { FleetArtifactsClient } from './services/artifacts'; import type { FleetRouter } from './types/request_context'; import { TelemetryEventsSender } from './telemetry/sender'; import { setupFleet } from './services/setup'; +import { BulkActionsResolver } from './services/agents'; export interface FleetSetupDeps { security: SecurityPluginSetup; @@ -109,6 +114,7 @@ export interface FleetSetupDeps { usageCollection?: UsageCollectionSetup; spaces: SpacesPluginStart; telemetry?: TelemetryPluginSetup; + taskManager: TaskManagerSetupContract; } export interface FleetStartDeps { @@ -118,6 +124,7 @@ export interface FleetStartDeps { security: SecurityPluginStart; telemetry?: TelemetryPluginStart; savedObjectsTagging: SavedObjectTaggingStart; + taskManager: TaskManagerStartContract; } export interface FleetAppContext { @@ -139,6 +146,7 @@ export interface FleetAppContext { logger?: Logger; httpSetup?: HttpServiceSetup; telemetryEventsSender: TelemetryEventsSender; + bulkActionsResolver: BulkActionsResolver; } export type FleetSetupContract = void; @@ -203,6 +211,7 @@ export class FleetPlugin private encryptedSavedObjectsSetup?: EncryptedSavedObjectsPluginSetup; private readonly telemetryEventsSender: TelemetryEventsSender; private readonly fleetStatus$: BehaviorSubject<ServiceStatus>; + private bulkActionsResolver?: BulkActionsResolver; private agentService?: AgentService; private packageService?: PackageService; @@ -388,6 +397,7 @@ export class FleetPlugin } this.telemetryEventsSender.setup(deps.telemetry); + this.bulkActionsResolver = new BulkActionsResolver(deps.taskManager, core); } public start(core: CoreStart, plugins: FleetStartDeps): FleetStartContract { @@ -412,10 +422,12 @@ export class FleetPlugin cloud: this.cloud, logger: this.logger, telemetryEventsSender: this.telemetryEventsSender, + bulkActionsResolver: this.bulkActionsResolver!, }); licenseService.start(plugins.licensing.license$); this.telemetryEventsSender.start(plugins.telemetry, core); + this.bulkActionsResolver?.start(plugins.taskManager); const logger = appContextService.getLogger(); diff --git a/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts index 61d86c983fc6ef..e64af66460ef46 100644 --- a/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/agent/actions_handlers.test.ts @@ -88,6 +88,7 @@ describe('test actions handlers', () => { }), createAgentAction: jest.fn().mockReturnValueOnce(agentAction), cancelAgentAction: jest.fn(), + getAgentActions: jest.fn(), } as jest.Mocked<ActionsService>; const postNewAgentActionHandler = postNewAgentActionHandlerBuilder(actionsService); diff --git a/x-pack/plugins/fleet/server/routes/agent/handlers.ts b/x-pack/plugins/fleet/server/routes/agent/handlers.ts index d6277cd4983fcb..b7d1a4907d8e0a 100644 --- a/x-pack/plugins/fleet/server/routes/agent/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/handlers.ts @@ -29,6 +29,7 @@ import type { PostBulkUpdateAgentTagsResponse, GetAgentTagsResponse, GetAvailableVersionsResponse, + GetActionStatusResponse, } from '../../../common/types'; import type { GetAgentsRequestSchema, @@ -149,7 +150,7 @@ export const bulkUpdateAgentTagsHandler: RequestHandler< request.body.tagsToRemove ?? [] ); - const body = results.items.reduce<PostBulkUpdateAgentTagsResponse>((acc, so) => { + const body = results.items.reduce<PostBulkUpdateAgentTagsResponse>((acc: any, so: any) => { acc[so.id] = { success: !so.error, error: so.error?.message, @@ -157,7 +158,7 @@ export const bulkUpdateAgentTagsHandler: RequestHandler< return acc; }, {}); - return response.ok({ body }); + return response.ok({ body: { ...body, actionId: results.actionId } }); } catch (error) { return defaultIngestErrorHandler({ error, response }); } @@ -273,7 +274,7 @@ export const postBulkAgentsReassignHandler: RequestHandler< return acc; }, {}); - return response.ok({ body }); + return response.ok({ body: { ...body, actionId: results.actionId } }); } catch (error) { return defaultIngestErrorHandler({ error, response }); } @@ -362,3 +363,16 @@ export const getAvailableVersionsHandler: RequestHandler = async (context, reque return defaultIngestErrorHandler({ error, response }); } }; + +export const getActionStatusHandler: RequestHandler = async (context, request, response) => { + const coreContext = await context.core; + const esClient = coreContext.elasticsearch.client.asInternalUser; + + try { + const actionStatuses = await AgentService.getActionStatuses(esClient); + const body: GetActionStatusResponse = { items: actionStatuses }; + return response.ok({ body }); + } catch (error) { + return defaultIngestErrorHandler({ error, response }); + } +}; diff --git a/x-pack/plugins/fleet/server/routes/agent/index.ts b/x-pack/plugins/fleet/server/routes/agent/index.ts index 7988a9883114e7..b551cd8d39bf4f 100644 --- a/x-pack/plugins/fleet/server/routes/agent/index.ts +++ b/x-pack/plugins/fleet/server/routes/agent/index.ts @@ -41,6 +41,7 @@ import { getAgentDataHandler, bulkUpdateAgentTagsHandler, getAvailableVersionsHandler, + getActionStatusHandler, } from './handlers'; import { postNewAgentActionHandlerBuilder, @@ -134,6 +135,7 @@ export const registerAPIRoutes = (router: FleetAuthzRouter, config: FleetConfigT getAgent: AgentService.getAgentById, cancelAgentAction: AgentService.cancelAgentAction, createAgentAction: AgentService.createAgentAction, + getAgentActions: AgentService.getAgentActions, }) ); @@ -149,6 +151,7 @@ export const registerAPIRoutes = (router: FleetAuthzRouter, config: FleetConfigT getAgent: AgentService.getAgentById, cancelAgentAction: AgentService.cancelAgentAction, createAgentAction: AgentService.createAgentAction, + getAgentActions: AgentService.getAgentActions, }) ); @@ -241,6 +244,18 @@ export const registerAPIRoutes = (router: FleetAuthzRouter, config: FleetConfigT getCurrentUpgradesHandler ); + // Current actions + router.get( + { + path: AGENT_API_ROUTES.ACTION_STATUS_PATTERN, + validate: false, + fleetAuthz: { + fleet: { all: true }, + }, + }, + getActionStatusHandler + ); + // Bulk reassign router.post( { diff --git a/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts b/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts index b6e398d269a6f8..8cc4a7b13e6878 100644 --- a/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/unenroll_handler.ts @@ -67,7 +67,7 @@ export const postBulkAgentsUnenrollHandler: RequestHandler< return acc; }, {}); - return response.ok({ body }); + return response.ok({ body: { ...body, actionId: results.actionId } }); } catch (error) { return defaultIngestErrorHandler({ error, response }); } diff --git a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts index d75e3ad07d9b87..ff78da6e63d1a2 100644 --- a/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/upgrade_handler.ts @@ -133,7 +133,7 @@ export const postBulkAgentsUpgradeHandler: RequestHandler< return acc; }, {}); - return response.ok({ body }); + return response.ok({ body: { ...body, actionId: results.actionId } }); } catch (error) { return defaultIngestErrorHandler({ error, response }); } diff --git a/x-pack/plugins/fleet/server/services/agents/action_runner.ts b/x-pack/plugins/fleet/server/services/agents/action_runner.ts new file mode 100644 index 00000000000000..634bf27ba23ef6 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/action_runner.ts @@ -0,0 +1,188 @@ +/* + * 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 uuid from 'uuid'; +import type { SortResults } from '@elastic/elasticsearch/lib/api/types'; +import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; + +import { isResponseError } from '@kbn/es-errors'; + +import type { Agent, BulkActionResult } from '../../types'; +import { appContextService } from '..'; +import { SO_SEARCH_LIMIT } from '../../../common/constants'; + +import { getAgentActions } from './actions'; +import { closePointInTime, getAgentsByKuery } from './crud'; + +export interface ActionParams { + kuery: string; + showInactive?: boolean; + batchSize?: number; + total?: number; + actionId?: string; + // additional parameters specific to an action e.g. reassign to new policy id + [key: string]: any; +} + +export interface RetryParams { + pitId: string; + searchAfter?: SortResults; + retryCount?: number; + taskId?: string; +} + +export abstract class ActionRunner { + protected esClient: ElasticsearchClient; + protected soClient: SavedObjectsClientContract; + + protected actionParams: ActionParams; + protected retryParams: RetryParams; + + constructor( + esClient: ElasticsearchClient, + soClient: SavedObjectsClientContract, + actionParams: ActionParams, + retryParams: RetryParams + ) { + this.esClient = esClient; + this.soClient = soClient; + this.actionParams = { ...actionParams, actionId: actionParams.actionId ?? uuid() }; + this.retryParams = retryParams; + } + + protected abstract getActionType(): string; + + protected abstract getTaskType(): string; + + protected abstract processAgents(agents: Agent[]): Promise<{ items: BulkActionResult[] }>; + + /** + * Common runner logic accross all agent bulk actions + * Starts action execution immeditalely, asynchronously + * On errors, starts a task with Task Manager to retry max 3 times + * If the last batch was stored in state, retry continues from there (searchAfter) + */ + public async runActionAsyncWithRetry(): Promise<{ items: BulkActionResult[]; actionId: string }> { + appContextService + .getLogger() + .info( + `Running action asynchronously, actionId: ${this.actionParams.actionId}, total agents: ${this.actionParams.total}` + ); + + withSpan({ name: this.getActionType(), type: 'action' }, () => + this.processAgentsInBatches().catch(async (error) => { + // 404 error comes when PIT query is closed + if (isResponseError(error) && error.statusCode === 404) { + const errorMessage = + '404 error from elasticsearch, not retrying. Error: ' + error.message; + appContextService.getLogger().warn(errorMessage); + return; + } + if (this.retryParams.retryCount) { + appContextService + .getLogger() + .error( + `Retry #${this.retryParams.retryCount} of task ${this.retryParams.taskId} failed: ${error.message}` + ); + + if (this.retryParams.retryCount === 3) { + const errorMessage = 'Stopping after 3rd retry. Error: ' + error.message; + appContextService.getLogger().warn(errorMessage); + return; + } + } else { + appContextService.getLogger().error(`Action failed: ${error.message}`); + } + const taskId = await appContextService.getBulkActionsResolver()!.run( + this.actionParams, + { + ...this.retryParams, + retryCount: (this.retryParams.retryCount ?? 0) + 1, + }, + this.getTaskType() + ); + + appContextService.getLogger().info(`Retrying in task: ${taskId}`); + }) + ); + + return { items: [], actionId: this.actionParams.actionId! }; + } + + private async processBatch(agents: Agent[]): Promise<{ items: BulkActionResult[] }> { + if (this.retryParams.retryCount) { + try { + const actions = await getAgentActions(this.esClient, this.actionParams!.actionId!); + + // skipping batch if there is already an action document present with last agent ids + for (const action of actions) { + if (action.agents?.[0] === agents[0].id) { + return { items: [] }; + } + } + } catch (error) { + appContextService.getLogger().debug(error.message); // if action not found, swallow + } + } + + return await this.processAgents(agents); + } + + async processAgentsInBatches(): Promise<{ items: BulkActionResult[] }> { + const start = Date.now(); + const pitId = this.retryParams.pitId; + + const perPage = this.actionParams.batchSize ?? SO_SEARCH_LIMIT; + + const getAgents = () => + getAgentsByKuery(this.esClient, { + kuery: this.actionParams.kuery, + showInactive: this.actionParams.showInactive ?? false, + page: 1, + perPage, + pitId, + searchAfter: this.retryParams.searchAfter, + }); + + const res = await getAgents(); + + let currentAgents = res.agents; + if (currentAgents.length === 0) { + appContextService + .getLogger() + .debug('currentAgents returned 0 hits, returning from bulk action query'); + return { items: [] }; // stop executing if there are no more results + } + + let results = await this.processBatch(currentAgents); + let allAgentsProcessed = currentAgents.length; + + while (allAgentsProcessed < res.total) { + const lastAgent = currentAgents[currentAgents.length - 1]; + this.retryParams.searchAfter = lastAgent.sort!; + const nextPage = await getAgents(); + currentAgents = nextPage.agents; + if (currentAgents.length === 0) { + appContextService + .getLogger() + .debug('currentAgents returned 0 hits, returning from bulk action query'); + break; // stop executing if there are no more results + } + const currentResults = await this.processBatch(currentAgents); + results = { items: results.items.concat(currentResults.items) }; + allAgentsProcessed += currentAgents.length; + } + + await closePointInTime(this.esClient, pitId!); + + appContextService + .getLogger() + .info(`processed ${allAgentsProcessed} agents, took ${Date.now() - start}ms`); + return { ...results }; + } +} diff --git a/x-pack/plugins/fleet/server/services/agents/action_status.ts b/x-pack/plugins/fleet/server/services/agents/action_status.ts new file mode 100644 index 00000000000000..bfda349ac3a05a --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/action_status.ts @@ -0,0 +1,142 @@ +/* + * 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 type { ElasticsearchClient } from '@kbn/core/server'; +import pMap from 'p-map'; + +import { SO_SEARCH_LIMIT } from '../../constants'; + +import type { FleetServerAgentAction, ActionStatus } from '../../types'; +import { AGENT_ACTIONS_INDEX, AGENT_ACTIONS_RESULTS_INDEX } from '../../../common'; + +/** + * Return current bulk actions + */ +export async function getActionStatuses(esClient: ElasticsearchClient): Promise<ActionStatus[]> { + let actions = await _getActions(esClient); + const cancelledActionIds = await _getCancelledActionId(esClient); + + // Fetch acknowledged result for every action + actions = await pMap( + actions, + async (action) => { + const { count } = await esClient.count({ + index: AGENT_ACTIONS_RESULTS_INDEX, + ignore_unavailable: true, + query: { + bool: { + must: [ + { + term: { + action_id: action.actionId, + }, + }, + ], + }, + }, + }); + + const nbAgentsActioned = action.nbAgentsActioned || action.nbAgentsActionCreated; + const complete = count === nbAgentsActioned; + const isCancelled = cancelledActionIds.indexOf(action.actionId) > -1; + + return { + ...action, + nbAgentsAck: count, + status: complete ? 'complete' : isCancelled ? 'cancelled' : action.status, + nbAgentsActioned, + }; + }, + { concurrency: 20 } + ); + + return actions; +} + +async function _getCancelledActionId(esClient: ElasticsearchClient) { + const res = await esClient.search<FleetServerAgentAction>({ + index: AGENT_ACTIONS_INDEX, + ignore_unavailable: true, + size: SO_SEARCH_LIMIT, + query: { + bool: { + must: [ + { + term: { + type: 'CANCEL', + }, + }, + { + exists: { + field: 'agents', + }, + }, + ], + }, + }, + }); + + return res.hits.hits.map((hit) => hit._source?.data?.target_id as string); +} + +async function _getActions(esClient: ElasticsearchClient) { + const res = await esClient.search<FleetServerAgentAction>({ + index: AGENT_ACTIONS_INDEX, + ignore_unavailable: true, + size: SO_SEARCH_LIMIT, + query: { + bool: { + must_not: [ + { + term: { + type: 'CANCEL', + }, + }, + ], + must: [ + { + exists: { + field: 'agents', + }, + }, + ], + }, + }, + body: { + sort: [{ '@timestamp': 'desc' }], + }, + }); + + return Object.values( + res.hits.hits.reduce((acc, hit) => { + if (!hit._source || !hit._source.action_id) { + return acc; + } + + if (!acc[hit._source.action_id]) { + const startTime = hit._source?.start_time ?? hit._source?.['@timestamp']; + const isExpired = hit._source?.expiration + ? Date.parse(hit._source?.expiration) < Date.now() + : false; + acc[hit._source.action_id] = { + actionId: hit._source.action_id, + nbAgentsActionCreated: 0, + nbAgentsAck: 0, + version: hit._source.data?.version as string, + startTime, + type: hit._source?.type, + nbAgentsActioned: hit._source?.total ?? 0, + status: isExpired ? 'expired' : 'in progress', + }; + } + + acc[hit._source.action_id].nbAgentsActionCreated += hit._source.agents?.length ?? 0; + + return acc; + }, {} as { [k: string]: ActionStatus }) + ); +} diff --git a/x-pack/plugins/fleet/server/services/agents/actions.ts b/x-pack/plugins/fleet/server/services/agents/actions.ts index f0e2d059a98a86..a2ba066db7d3fc 100644 --- a/x-pack/plugins/fleet/server/services/agents/actions.ts +++ b/x-pack/plugins/fleet/server/services/agents/actions.ts @@ -36,6 +36,7 @@ export async function createAgentAction( type: newAgentAction.type, start_time: newAgentAction.start_time, minimum_execution_duration: newAgentAction.minimum_execution_duration, + total: newAgentAction.total, }; await esClient.create({ @@ -96,6 +97,33 @@ export async function bulkCreateAgentActions( return actions; } +export async function getAgentActions(esClient: ElasticsearchClient, actionId: string) { + const res = await esClient.search<FleetServerAgentAction>({ + index: AGENT_ACTIONS_INDEX, + query: { + bool: { + must: [ + { + term: { + action_id: actionId, + }, + }, + ], + }, + }, + size: SO_SEARCH_LIMIT, + }); + + if (res.hits.hits.length === 0) { + throw new AgentActionNotFoundError('Action not found'); + } + + return res.hits.hits.map((hit) => ({ + ...hit._source, + id: hit._id, + })); +} + export async function cancelAgentAction(esClient: ElasticsearchClient, actionId: string) { const res = await esClient.search<FleetServerAgentAction>({ index: AGENT_ACTIONS_INDEX, @@ -163,4 +191,6 @@ export interface ActionsService { esClient: ElasticsearchClient, newAgentAction: Omit<AgentAction, 'id'> ) => Promise<AgentAction>; + + getAgentActions: (esClient: ElasticsearchClient, actionId: string) => Promise<any[]>; } diff --git a/x-pack/plugins/fleet/server/services/agents/bulk_actions_resolver.ts b/x-pack/plugins/fleet/server/services/agents/bulk_actions_resolver.ts new file mode 100644 index 00000000000000..e80db905d48e0a --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/bulk_actions_resolver.ts @@ -0,0 +1,161 @@ +/* + * 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 { SavedObjectsClient } from '@kbn/core/server'; +import type { CoreSetup, ElasticsearchClient } from '@kbn/core/server'; +import type { + ConcreteTaskInstance, + TaskManagerStartContract, + TaskManagerSetupContract, +} from '@kbn/task-manager-plugin/server'; +import moment from 'moment'; + +import { appContextService } from '../app_context'; + +import { ReassignActionRunner } from './reassign_action_runner'; +import { UpgradeActionRunner } from './upgrade_action_runner'; +import { UpdateAgentTagsActionRunner } from './update_agent_tags_action_runner'; +import { UnenrollActionRunner } from './unenroll_action_runner'; +import type { ActionParams, RetryParams } from './action_runner'; + +export enum BulkActionTaskType { + REASSIGN_RETRY = 'fleet:reassign_action:retry', + UNENROLL_RETRY = 'fleet:unenroll_action:retry', + UPGRADE_RETRY = 'fleet:upgrade_action:retry', + UPDATE_AGENT_TAGS_RETRY = 'fleet:update_agent_tags:retry', +} + +/** + * Create and run retry tasks of agent bulk actions + */ +export class BulkActionsResolver { + private taskManager?: TaskManagerStartContract; + + createTaskRunner(core: CoreSetup, taskType: BulkActionTaskType) { + return ({ taskInstance }: { taskInstance: ConcreteTaskInstance }) => { + const getDeps = async () => { + const [coreStart] = await core.getStartServices(); + return { + esClient: coreStart.elasticsearch.client.asInternalUser, + soClient: new SavedObjectsClient(coreStart.savedObjects.createInternalRepository()), + }; + }; + + const runnerMap = { + [BulkActionTaskType.UNENROLL_RETRY]: UnenrollActionRunner, + [BulkActionTaskType.REASSIGN_RETRY]: ReassignActionRunner, + [BulkActionTaskType.UPDATE_AGENT_TAGS_RETRY]: UpdateAgentTagsActionRunner, + [BulkActionTaskType.UPGRADE_RETRY]: UpgradeActionRunner, + }; + + return createRetryTask( + taskInstance, + getDeps, + async ( + esClient: ElasticsearchClient, + soClient: SavedObjectsClient, + actionParams: ActionParams, + retryParams: RetryParams + ) => + await new runnerMap[taskType]( + esClient, + soClient, + actionParams, + retryParams + ).runActionAsyncWithRetry() + ); + }; + } + + constructor(taskManager: TaskManagerSetupContract, core: CoreSetup) { + const definitions = Object.values(BulkActionTaskType) + .map((type) => { + return [ + type, + { + title: 'Bulk Action Retry', + timeout: '1m', + maxAttempts: 1, + createTaskRunner: this.createTaskRunner(core, type), + }, + ]; + }) + .reduce((acc, current) => { + acc[current[0] as string] = current[1]; + return acc; + }, {} as any); + taskManager.registerTaskDefinitions(definitions); + } + + public async start(taskManager: TaskManagerStartContract) { + this.taskManager = taskManager; + } + + getTaskId(actionId: string, type: string) { + return `${type}:${actionId}`; + } + + public async run( + actionParams: ActionParams, + retryParams: RetryParams, + taskType: string, + runAt?: Date + ) { + const taskId = this.getTaskId(actionParams.actionId!, taskType); + await this.taskManager?.ensureScheduled({ + id: taskId, + taskType, + scope: ['fleet'], + state: {}, + params: { actionParams, retryParams }, + runAt: + runAt ?? + moment(new Date()) + .add(Math.pow(3, retryParams.retryCount ?? 1), 's') + .toDate(), + }); + appContextService.getLogger().info('Running task ' + taskId); + return taskId; + } +} + +export function createRetryTask( + taskInstance: ConcreteTaskInstance, + getDeps: () => Promise<{ esClient: ElasticsearchClient; soClient: SavedObjectsClient }>, + doRetry: ( + esClient: ElasticsearchClient, + soClient: SavedObjectsClient, + actionParams: ActionParams, + retryParams: RetryParams + ) => void +) { + return { + async run() { + appContextService.getLogger().info('Running bulk action retry task'); + + const { esClient, soClient } = await getDeps(); + + const retryParams = taskInstance.params.retryParams; + + appContextService + .getLogger() + .debug(`Retry #${retryParams.retryCount} of task ${taskInstance.id}`); + + if (retryParams.searchAfter) { + appContextService.getLogger().info('Continuing task from batch ' + retryParams.searchAfter); + } + + doRetry(esClient, soClient, taskInstance.params.actionParams, { + ...retryParams, + taskId: taskInstance.id, + }); + + appContextService.getLogger().info('Completed bulk action retry task'); + }, + + async cancel() {}, + }; +} diff --git a/x-pack/plugins/fleet/server/services/agents/crud.test.ts b/x-pack/plugins/fleet/server/services/agents/crud.test.ts index dbc2017c95cf52..c6d63b35ac7be2 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.test.ts @@ -9,7 +9,7 @@ import type { ElasticsearchClient } from '@kbn/core/server'; import type { Agent } from '../../types'; -import { errorsToResults, getAgentsByKuery, getAgentTags, processAgentsInBatches } from './crud'; +import { errorsToResults, getAgentsByKuery, getAgentTags } from './crud'; jest.mock('../../../common/services/is_agent_upgradeable', () => ({ isAgentUpgradeable: jest.fn().mockImplementation((agent: Agent) => agent.id.includes('up')), @@ -293,53 +293,6 @@ describe('Agents CRUD test', () => { }); }); - describe('processAgentsInBatches', () => { - const mockProcessAgents = (agents: Agent[]) => - Promise.resolve({ items: agents.map((agent) => ({ id: agent.id, success: true })) }); - it('should return results for multiple batches', async () => { - searchMock - .mockImplementationOnce(() => Promise.resolve(getEsResponse(['1', '2'], 3))) - .mockImplementationOnce(() => Promise.resolve(getEsResponse(['3'], 3))); - - const response = await processAgentsInBatches( - esClientMock, - { - kuery: 'active:true', - batchSize: 2, - showInactive: false, - }, - mockProcessAgents - ); - expect(response).toEqual({ - items: [ - { id: '1', success: true }, - { id: '2', success: true }, - { id: '3', success: true }, - ], - }); - }); - - it('should return results for one batch', async () => { - searchMock.mockImplementationOnce(() => Promise.resolve(getEsResponse(['1', '2', '3'], 3))); - - const response = await processAgentsInBatches( - esClientMock, - { - kuery: 'active:true', - showInactive: false, - }, - mockProcessAgents - ); - expect(response).toEqual({ - items: [ - { id: '1', success: true }, - { id: '2', success: true }, - { id: '3', success: true }, - ], - }); - }); - }); - describe('errorsToResults', () => { it('should transform errors to results', () => { const results = errorsToResults([{ id: '1' } as Agent, { id: '2' } as Agent], { diff --git a/x-pack/plugins/fleet/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts index 5b6e39c153b895..193bc71d04d292 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.ts @@ -4,12 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import Boom from '@hapi/boom'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SortResults } from '@elastic/elasticsearch/lib/api/types'; import type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/server'; - import type { KueryNode } from '@kbn/es-query'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; @@ -254,55 +252,6 @@ export async function getAgentsByKuery( }; } -export async function processAgentsInBatches( - esClient: ElasticsearchClient, - options: Omit<ListWithKuery, 'page' | 'perPage'> & { - showInactive: boolean; - batchSize?: number; - }, - processAgents: ( - agents: Agent[], - includeSuccess: boolean - ) => Promise<{ items: BulkActionResult[] }> -): Promise<{ items: BulkActionResult[] }> { - const pitId = await openPointInTime(esClient); - - const perPage = options.batchSize ?? SO_SEARCH_LIMIT; - - const res = await getAgentsByKuery(esClient, { - ...options, - page: 1, - perPage, - pitId, - }); - - let currentAgents = res.agents; - // include successful agents if total agents does not exceed 10k - const skipSuccess = res.total > SO_SEARCH_LIMIT; - - let results = await processAgents(currentAgents, skipSuccess); - let allAgentsProcessed = currentAgents.length; - - while (allAgentsProcessed < res.total) { - const lastAgent = currentAgents[currentAgents.length - 1]; - const nextPage = await getAgentsByKuery(esClient, { - ...options, - page: 1, - perPage, - pitId, - searchAfter: lastAgent.sort!, - }); - currentAgents = nextPage.agents; - const currentResults = await processAgents(currentAgents, skipSuccess); - results = { items: results.items.concat(currentResults.items) }; - allAgentsProcessed += currentAgents.length; - } - - await closePointInTime(esClient, pitId); - - return results; -} - export function errorsToResults( agents: Agent[], errors: Record<Agent['id'], Error>, diff --git a/x-pack/plugins/fleet/server/services/agents/current_upgrades.ts b/x-pack/plugins/fleet/server/services/agents/current_upgrades.ts new file mode 100644 index 00000000000000..229074acde82b9 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/current_upgrades.ts @@ -0,0 +1,150 @@ +/* + * 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 type { ElasticsearchClient } from '@kbn/core/server'; +import pMap from 'p-map'; + +import type { FleetServerAgentAction, CurrentUpgrade } from '../../types'; +import { AGENT_ACTIONS_INDEX, AGENT_ACTIONS_RESULTS_INDEX } from '../../../common'; +import { SO_SEARCH_LIMIT } from '../../constants'; + +/** + * Return current bulk upgrades (non completed or cancelled) + */ +export async function getCurrentBulkUpgrades( + esClient: ElasticsearchClient, + now = new Date().toISOString() +): Promise<CurrentUpgrade[]> { + // Fetch all non expired actions + const [_upgradeActions, cancelledActionIds] = await Promise.all([ + _getUpgradeActions(esClient, now), + _getCancelledActionId(esClient, now), + ]); + + let upgradeActions = _upgradeActions.filter( + (action) => cancelledActionIds.indexOf(action.actionId) < 0 + ); + + // Fetch acknowledged result for every upgrade action + upgradeActions = await pMap( + upgradeActions, + async (upgradeAction) => { + const { count } = await esClient.count({ + index: AGENT_ACTIONS_RESULTS_INDEX, + ignore_unavailable: true, + query: { + bool: { + must: [ + { + term: { + action_id: upgradeAction.actionId, + }, + }, + ], + }, + }, + }); + + return { + ...upgradeAction, + nbAgentsAck: count, + complete: upgradeAction.nbAgents <= count, + }; + }, + { concurrency: 20 } + ); + + upgradeActions = upgradeActions.filter((action) => !action.complete); + + return upgradeActions; +} + +async function _getCancelledActionId( + esClient: ElasticsearchClient, + now = new Date().toISOString() +) { + const res = await esClient.search<FleetServerAgentAction>({ + index: AGENT_ACTIONS_INDEX, + ignore_unavailable: true, + size: SO_SEARCH_LIMIT, + query: { + bool: { + must: [ + { + term: { + type: 'CANCEL', + }, + }, + { + exists: { + field: 'agents', + }, + }, + { + range: { + expiration: { gte: now }, + }, + }, + ], + }, + }, + }); + + return res.hits.hits.map((hit) => hit._source?.data?.target_id as string); +} + +async function _getUpgradeActions(esClient: ElasticsearchClient, now = new Date().toISOString()) { + const res = await esClient.search<FleetServerAgentAction>({ + index: AGENT_ACTIONS_INDEX, + ignore_unavailable: true, + size: SO_SEARCH_LIMIT, + query: { + bool: { + must: [ + { + term: { + type: 'UPGRADE', + }, + }, + { + exists: { + field: 'agents', + }, + }, + { + range: { + expiration: { gte: now }, + }, + }, + ], + }, + }, + }); + + return Object.values( + res.hits.hits.reduce((acc, hit) => { + if (!hit._source || !hit._source.action_id) { + return acc; + } + + if (!acc[hit._source.action_id]) { + acc[hit._source.action_id] = { + actionId: hit._source.action_id, + nbAgents: 0, + complete: false, + nbAgentsAck: 0, + version: hit._source.data?.version as string, + startTime: hit._source?.start_time, + }; + } + + acc[hit._source.action_id].nbAgents += hit._source.agents?.length ?? 0; + + return acc; + }, {} as { [k: string]: CurrentUpgrade }) + ); +} diff --git a/x-pack/plugins/fleet/server/services/agents/index.ts b/x-pack/plugins/fleet/server/services/agents/index.ts index 7712c614adbea0..302790cf6ae6d8 100644 --- a/x-pack/plugins/fleet/server/services/agents/index.ts +++ b/x-pack/plugins/fleet/server/services/agents/index.ts @@ -14,5 +14,8 @@ export * from './actions'; export * from './reassign'; export * from './setup'; export * from './update_agent_tags'; +export * from './action_status'; export { AgentServiceImpl } from './agent_service'; export type { AgentClient, AgentService } from './agent_service'; +export { BulkActionsResolver } from './bulk_actions_resolver'; +export { getCurrentBulkUpgrades } from './current_upgrades'; diff --git a/x-pack/plugins/fleet/server/services/agents/reassign.ts b/x-pack/plugins/fleet/server/services/agents/reassign.ts index 1746d324d626ff..9889bc8a6eada2 100644 --- a/x-pack/plugins/fleet/server/services/agents/reassign.ts +++ b/x-pack/plugins/fleet/server/services/agents/reassign.ts @@ -12,18 +12,20 @@ import type { Agent, BulkActionResult } from '../../types'; import { agentPolicyService } from '../agent_policy'; import { AgentReassignmentError, HostedAgentPolicyRestrictionRelatedError } from '../../errors'; +import { SO_SEARCH_LIMIT } from '../../constants'; + import { getAgentDocuments, getAgentPolicyForAgent, updateAgent, - bulkUpdateAgents, - processAgentsInBatches, - errorsToResults, + getAgentsByKuery, + openPointInTime, } from './crud'; import type { GetAgentsOptions } from '.'; import { createAgentAction } from './actions'; import { searchHitToAgent } from './helpers'; -import { getHostedPolicies, isHostedAgent } from './hosted_agent'; + +import { ReassignActionRunner, reassignBatch } from './reassign_action_runner'; export async function reassignAgent( soClient: SavedObjectsClientContract, @@ -79,9 +81,12 @@ function isMgetDoc(doc?: estypes.MgetResponseItem<unknown>): doc is estypes.GetG export async function reassignAgents( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - options: ({ agents: Agent[] } | GetAgentsOptions) & { force?: boolean; batchSize?: number }, + options: ({ agents: Agent[] } | GetAgentsOptions) & { + force?: boolean; + batchSize?: number; + }, newAgentPolicyId: string -): Promise<{ items: BulkActionResult[] }> { +): Promise<{ items: BulkActionResult[]; actionId?: string }> { const newAgentPolicy = await agentPolicyService.get(soClient, newAgentPolicyId); if (!newAgentPolicy) { throw Boom.notFound(`Agent policy not found: ${newAgentPolicyId}`); @@ -108,94 +113,37 @@ export async function reassignAgents( } } } else if ('kuery' in options) { - return await processAgentsInBatches( - esClient, - { - kuery: options.kuery, - showInactive: options.showInactive ?? false, - batchSize: options.batchSize, - }, - async (agents: Agent[], skipSuccess: boolean) => - await reassignBatch( - soClient, - esClient, + const batchSize = options.batchSize ?? SO_SEARCH_LIMIT; + const res = await getAgentsByKuery(esClient, { + kuery: options.kuery, + showInactive: options.showInactive ?? false, + page: 1, + perPage: batchSize, + }); + // running action in async mode for >10k agents (or actions > batchSize for testing purposes) + if (res.total <= batchSize) { + givenAgents = res.agents; + } else { + return await new ReassignActionRunner( + esClient, + soClient, + { + ...options, + batchSize, + total: res.total, newAgentPolicyId, - agents, - outgoingErrors, - undefined, - skipSuccess - ) - ); + }, + { pitId: await openPointInTime(esClient) } + ).runActionAsyncWithRetry(); + } } return await reassignBatch( soClient, esClient, - newAgentPolicyId, + { newAgentPolicyId }, givenAgents, outgoingErrors, 'agentIds' in options ? options.agentIds : undefined ); } - -async function reassignBatch( - soClient: SavedObjectsClientContract, - esClient: ElasticsearchClient, - newAgentPolicyId: string, - givenAgents: Agent[], - outgoingErrors: Record<Agent['id'], Error>, - agentIds?: string[], - skipSuccess?: boolean -): Promise<{ items: BulkActionResult[] }> { - const errors: Record<Agent['id'], Error> = { ...outgoingErrors }; - - const hostedPolicies = await getHostedPolicies(soClient, givenAgents); - - // which are allowed to unenroll - const agentResults = await Promise.allSettled( - givenAgents.map(async (agent, index) => { - if (agent.policy_id === newAgentPolicyId) { - throw new AgentReassignmentError(`${agent.id} is already assigned to ${newAgentPolicyId}`); - } - - if (isHostedAgent(hostedPolicies, agent)) { - throw new HostedAgentPolicyRestrictionRelatedError( - `Cannot reassign an agent from hosted agent policy ${agent.policy_id}` - ); - } - - return agent; - }) - ); - - // Filter to agents that do not already use the new agent policy ID - const agentsToUpdate = agentResults.reduce<Agent[]>((agents, result, index) => { - if (result.status === 'fulfilled') { - agents.push(result.value); - } else { - const id = givenAgents[index].id; - errors[id] = result.reason; - } - return agents; - }, []); - - await bulkUpdateAgents( - esClient, - agentsToUpdate.map((agent) => ({ - agentId: agent.id, - data: { - policy_id: newAgentPolicyId, - policy_revision: null, - }, - })) - ); - - const now = new Date().toISOString(); - await createAgentAction(esClient, { - agents: agentsToUpdate.map((agent) => agent.id), - created_at: now, - type: 'POLICY_REASSIGN', - }); - - return { items: errorsToResults(givenAgents, errors, agentIds, skipSuccess) }; -} diff --git a/x-pack/plugins/fleet/server/services/agents/reassign_action_runner.ts b/x-pack/plugins/fleet/server/services/agents/reassign_action_runner.ts new file mode 100644 index 00000000000000..c1bdb0e467c0da --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/reassign_action_runner.ts @@ -0,0 +1,108 @@ +/* + * 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 type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/server'; + +import type { Agent, BulkActionResult } from '../../types'; + +import { AgentReassignmentError, HostedAgentPolicyRestrictionRelatedError } from '../../errors'; + +import { appContextService } from '../app_context'; + +import { ActionRunner } from './action_runner'; + +import { errorsToResults, bulkUpdateAgents } from './crud'; +import { createAgentAction } from './actions'; +import { getHostedPolicies, isHostedAgent } from './hosted_agent'; +import { BulkActionTaskType } from './bulk_actions_resolver'; + +export class ReassignActionRunner extends ActionRunner { + protected async processAgents(agents: Agent[]): Promise<{ items: BulkActionResult[] }> { + return await reassignBatch( + this.soClient, + this.esClient, + this.actionParams! as any, + agents, + {}, + undefined, + true + ); + } + + protected getTaskType() { + return BulkActionTaskType.REASSIGN_RETRY; + } + + protected getActionType() { + return 'POLICY_REASSIGN'; + } +} + +export async function reassignBatch( + soClient: SavedObjectsClientContract, + esClient: ElasticsearchClient, + options: { + newAgentPolicyId: string; + actionId?: string; + total?: number; + }, + givenAgents: Agent[], + outgoingErrors: Record<Agent['id'], Error>, + agentIds?: string[], + skipSuccess?: boolean +): Promise<{ items: BulkActionResult[] }> { + const errors: Record<Agent['id'], Error> = { ...outgoingErrors }; + + const hostedPolicies = await getHostedPolicies(soClient, givenAgents); + + const agentsToUpdate = givenAgents.reduce<Agent[]>((agents, agent) => { + if (agent.policy_id === options.newAgentPolicyId) { + errors[agent.id] = new AgentReassignmentError( + `${agent.id} is already assigned to ${options.newAgentPolicyId}` + ); + } else if (isHostedAgent(hostedPolicies, agent)) { + errors[agent.id] = new HostedAgentPolicyRestrictionRelatedError( + `Cannot reassign an agent from hosted agent policy ${agent.policy_id}` + ); + } else { + agents.push(agent); + } + return agents; + }, []); + + const result = { items: errorsToResults(givenAgents, errors, agentIds, skipSuccess) }; + + if (agentsToUpdate.length === 0) { + // early return if all agents failed validation + appContextService + .getLogger() + .debug('No agents to update, skipping agent update and action creation'); + return result; + } + + await bulkUpdateAgents( + esClient, + agentsToUpdate.map((agent) => ({ + agentId: agent.id, + data: { + policy_id: options.newAgentPolicyId, + policy_revision: null, + }, + })) + ); + + const now = new Date().toISOString(); + await createAgentAction(esClient, { + id: options.actionId, + agents: agentsToUpdate.map((agent) => agent.id), + created_at: now, + type: 'POLICY_REASSIGN', + total: options.total, + }); + + return result; +} diff --git a/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts b/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts index 9ad39990b9ffa0..668ab79da691fa 100644 --- a/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts @@ -12,7 +12,8 @@ import type { AgentPolicy } from '../../types'; import { HostedAgentPolicyRestrictionRelatedError } from '../../errors'; import { invalidateAPIKeys } from '../api_keys'; -import { invalidateAPIKeysForAgents, unenrollAgent, unenrollAgents } from './unenroll'; +import { unenrollAgent, unenrollAgents } from './unenroll'; +import { invalidateAPIKeysForAgents } from './unenroll_action_runner'; jest.mock('../api_keys'); diff --git a/x-pack/plugins/fleet/server/services/agents/unenroll.ts b/x-pack/plugins/fleet/server/services/agents/unenroll.ts index d8a5b4b32a101b..941e1260894b46 100644 --- a/x-pack/plugins/fleet/server/services/agents/unenroll.ts +++ b/x-pack/plugins/fleet/server/services/agents/unenroll.ts @@ -8,21 +8,19 @@ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; import type { Agent, BulkActionResult } from '../../types'; -import { invalidateAPIKeys } from '../api_keys'; import { HostedAgentPolicyRestrictionRelatedError } from '../../errors'; +import { SO_SEARCH_LIMIT } from '../../constants'; import { createAgentAction } from './actions'; import type { GetAgentsOptions } from './crud'; -import { errorsToResults } from './crud'; +import { openPointInTime } from './crud'; +import { getAgentsByKuery } from './crud'; +import { getAgentById, getAgents, updateAgent, getAgentPolicyForAgent } from './crud'; import { - getAgentById, - getAgents, - updateAgent, - getAgentPolicyForAgent, - bulkUpdateAgents, - processAgentsInBatches, -} from './crud'; -import { getHostedPolicies, isHostedAgent } from './hosted_agent'; + invalidateAPIKeysForAgents, + UnenrollActionRunner, + unenrollBatch, +} from './unenroll_action_runner'; async function unenrollAgentIsAllowed( soClient: SavedObjectsClientContract, @@ -73,104 +71,33 @@ export async function unenrollAgents( revoke?: boolean; batchSize?: number; } -): Promise<{ items: BulkActionResult[] }> { +): Promise<{ items: BulkActionResult[]; actionId?: string }> { if ('agentIds' in options) { const givenAgents = await getAgents(esClient, options); return await unenrollBatch(soClient, esClient, givenAgents, options); } - return await processAgentsInBatches( - esClient, - { - kuery: options.kuery, - showInactive: options.showInactive ?? false, - batchSize: options.batchSize, - }, - async (agents: Agent[], skipSuccess?: boolean) => - await unenrollBatch(soClient, esClient, agents, options, skipSuccess) - ); -} -async function unenrollBatch( - soClient: SavedObjectsClientContract, - esClient: ElasticsearchClient, - givenAgents: Agent[], - options: { - force?: boolean; - revoke?: boolean; - }, - skipSuccess?: boolean -): Promise<{ items: BulkActionResult[] }> { - // Filter to those not already unenrolled, or unenrolling - const agentsEnrolled = givenAgents.filter((agent) => { - if (options.revoke) { - return !agent.unenrolled_at; - } - return !agent.unenrollment_started_at && !agent.unenrolled_at; + const batchSize = options.batchSize ?? SO_SEARCH_LIMIT; + const res = await getAgentsByKuery(esClient, { + kuery: options.kuery, + showInactive: options.showInactive ?? false, + page: 1, + perPage: batchSize, }); - - const hostedPolicies = await getHostedPolicies(soClient, agentsEnrolled); - - const outgoingErrors: Record<Agent['id'], Error> = {}; - - // And which are allowed to unenroll - const agentsToUpdate = options.force - ? agentsEnrolled - : agentsEnrolled.reduce<Agent[]>((agents, agent, index) => { - if (isHostedAgent(hostedPolicies, agent)) { - const id = givenAgents[index].id; - outgoingErrors[id] = new HostedAgentPolicyRestrictionRelatedError( - `Cannot unenroll ${agent.id} from a hosted agent policy ${agent.policy_id}` - ); - } else { - agents.push(agent); - } - return agents; - }, []); - - const now = new Date().toISOString(); - if (options.revoke) { - // Get all API keys that need to be invalidated - await invalidateAPIKeysForAgents(agentsToUpdate); + if (res.total <= batchSize) { + const givenAgents = await getAgents(esClient, options); + return await unenrollBatch(soClient, esClient, givenAgents, options); } else { - // Create unenroll action for each agent - await createAgentAction(esClient, { - agents: agentsToUpdate.map((agent) => agent.id), - created_at: now, - type: 'UNENROLL', - }); - } - - // Update the necessary agents - const updateData = options.revoke - ? { unenrolled_at: now, active: false } - : { unenrollment_started_at: now }; - - await bulkUpdateAgents( - esClient, - agentsToUpdate.map(({ id }) => ({ agentId: id, data: updateData })) - ); - - return { - items: errorsToResults(givenAgents, outgoingErrors, undefined, skipSuccess), - }; -} - -export async function invalidateAPIKeysForAgents(agents: Agent[]) { - const apiKeys = agents.reduce<string[]>((keys, agent) => { - if (agent.access_api_key_id) { - keys.push(agent.access_api_key_id); - } - if (agent.default_api_key_id) { - keys.push(agent.default_api_key_id); - } - if (agent.default_api_key_history) { - agent.default_api_key_history.forEach((apiKey) => keys.push(apiKey.id)); - } - return keys; - }, []); - - if (apiKeys.length) { - await invalidateAPIKeys(apiKeys); + return await new UnenrollActionRunner( + esClient, + soClient, + { + ...options, + batchSize, + total: res.total, + }, + { pitId: await openPointInTime(esClient) } + ).runActionAsyncWithRetry(); } } diff --git a/x-pack/plugins/fleet/server/services/agents/unenroll_action_runner.ts b/x-pack/plugins/fleet/server/services/agents/unenroll_action_runner.ts new file mode 100644 index 00000000000000..6eda4b00499e17 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/unenroll_action_runner.ts @@ -0,0 +1,122 @@ +/* + * 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 type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/server'; + +import type { Agent, BulkActionResult } from '../../types'; + +import { HostedAgentPolicyRestrictionRelatedError } from '../../errors'; + +import { invalidateAPIKeys } from '../api_keys'; + +import { ActionRunner } from './action_runner'; + +import { errorsToResults, bulkUpdateAgents } from './crud'; +import { createAgentAction } from './actions'; +import { getHostedPolicies, isHostedAgent } from './hosted_agent'; +import { BulkActionTaskType } from './bulk_actions_resolver'; + +export class UnenrollActionRunner extends ActionRunner { + protected async processAgents(agents: Agent[]): Promise<{ items: BulkActionResult[] }> { + return await unenrollBatch(this.soClient, this.esClient, agents, this.actionParams!, true); + } + + protected getTaskType() { + return BulkActionTaskType.UNENROLL_RETRY; + } + + protected getActionType() { + return 'UNENROLL'; + } +} + +export async function unenrollBatch( + soClient: SavedObjectsClientContract, + esClient: ElasticsearchClient, + givenAgents: Agent[], + options: { + force?: boolean; + revoke?: boolean; + actionId?: string; + total?: number; + }, + skipSuccess?: boolean +): Promise<{ items: BulkActionResult[] }> { + // Filter to those not already unenrolled, or unenrolling + const agentsEnrolled = givenAgents.filter((agent) => { + if (options.revoke) { + return !agent.unenrolled_at; + } + return !agent.unenrollment_started_at && !agent.unenrolled_at; + }); + + const hostedPolicies = await getHostedPolicies(soClient, agentsEnrolled); + + const outgoingErrors: Record<Agent['id'], Error> = {}; + + // And which are allowed to unenroll + const agentsToUpdate = options.force + ? agentsEnrolled + : agentsEnrolled.reduce<Agent[]>((agents, agent) => { + if (isHostedAgent(hostedPolicies, agent)) { + outgoingErrors[agent.id] = new HostedAgentPolicyRestrictionRelatedError( + `Cannot unenroll ${agent.id} from a hosted agent policy ${agent.policy_id}` + ); + } else { + agents.push(agent); + } + return agents; + }, []); + + const now = new Date().toISOString(); + if (options.revoke) { + // Get all API keys that need to be invalidated + await invalidateAPIKeysForAgents(agentsToUpdate); + } else { + // Create unenroll action for each agent + await createAgentAction(esClient, { + id: options.actionId, + agents: agentsToUpdate.map((agent) => agent.id), + created_at: now, + type: 'UNENROLL', + total: options.total, + }); + } + + // Update the necessary agents + const updateData = options.revoke + ? { unenrolled_at: now, active: false } + : { unenrollment_started_at: now }; + + await bulkUpdateAgents( + esClient, + agentsToUpdate.map(({ id }) => ({ agentId: id, data: updateData })) + ); + + return { + items: errorsToResults(givenAgents, outgoingErrors, undefined, skipSuccess), + }; +} + +export async function invalidateAPIKeysForAgents(agents: Agent[]) { + const apiKeys = agents.reduce<string[]>((keys, agent) => { + if (agent.access_api_key_id) { + keys.push(agent.access_api_key_id); + } + if (agent.default_api_key_id) { + keys.push(agent.default_api_key_id); + } + if (agent.default_api_key_history) { + agent.default_api_key_history.forEach((apiKey) => keys.push(apiKey.id)); + } + return keys; + }, []); + + if (apiKeys.length) { + await invalidateAPIKeys(apiKeys); + } +} diff --git a/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts b/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts index 748f85db2843bd..7ac8e4e3f9e78a 100644 --- a/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/update_agent_tags.test.ts @@ -16,6 +16,14 @@ jest.mock('./filter_hosted_agents', () => ({ .mockImplementation((soClient, givenAgents) => Promise.resolve(givenAgents)), })); +const mockRunAsync = jest.fn().mockResolvedValue({}); +jest.mock('./update_agent_tags_action_runner', () => ({ + ...jest.requireActual('./update_agent_tags_action_runner'), + UpdateAgentTagsActionRunner: jest.fn().mockImplementation(() => { + return { runActionAsyncWithRetry: mockRunAsync }; + }), +})); + describe('update_agent_tags', () => { let esClient: ElasticsearchClientMock; let soClient: jest.Mocked<SavedObjectsClientContract>; @@ -36,6 +44,8 @@ describe('update_agent_tags', () => { esClient.bulk.mockResolvedValue({ items: [], } as any); + + mockRunAsync.mockClear(); }); function expectTagsInEsBulk(tags: string[]) { @@ -114,4 +124,33 @@ describe('update_agent_tags', () => { expectTagsInEsBulk(['three', 'newName']); }); + + it('should run add tags async when actioning more agents than batch size', async () => { + esClient.search.mockResolvedValue({ + hits: { + total: 3, + hits: [ + { + _id: 'agent1', + _source: {}, + } as any, + { + _id: 'agent2', + _source: {}, + } as any, + { + _id: 'agent3', + _source: {}, + } as any, + ], + }, + took: 0, + timed_out: false, + _shards: {} as any, + }); + + await updateAgentTags(soClient, esClient, { kuery: '', batchSize: 2 }, ['newName'], []); + + expect(mockRunAsync).toHaveBeenCalled(); + }); }); diff --git a/x-pack/plugins/fleet/server/services/agents/update_agent_tags.ts b/x-pack/plugins/fleet/server/services/agents/update_agent_tags.ts index c4893c77696516..4496e16cbc4766 100644 --- a/x-pack/plugins/fleet/server/services/agents/update_agent_tags.ts +++ b/x-pack/plugins/fleet/server/services/agents/update_agent_tags.ts @@ -5,22 +5,18 @@ * 2.0. */ -import { difference, uniq } from 'lodash'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; import type { Agent, BulkActionResult } from '../../types'; import { AgentReassignmentError } from '../../errors'; -import { - getAgentDocuments, - bulkUpdateAgents, - processAgentsInBatches, - errorsToResults, -} from './crud'; +import { SO_SEARCH_LIMIT } from '../../constants'; + +import { getAgentDocuments, getAgentsByKuery, openPointInTime } from './crud'; import type { GetAgentsOptions } from '.'; import { searchHitToAgent } from './helpers'; -import { filterHostedPolicies } from './filter_hosted_agents'; +import { UpdateAgentTagsActionRunner, updateTagsBatch } from './update_agent_tags_action_runner'; function isMgetDoc(doc?: estypes.MgetResponseItem<unknown>): doc is estypes.GetGetResult { return Boolean(doc && 'found' in doc); @@ -32,9 +28,9 @@ export async function updateAgentTags( options: ({ agents: Agent[] } | GetAgentsOptions) & { batchSize?: number }, tagsToAdd: string[], tagsToRemove: string[] -) { +): Promise<{ items: BulkActionResult[]; actionId?: string }> { const outgoingErrors: Record<Agent['id'], Error> = {}; - const givenAgents: Agent[] = []; + let givenAgents: Agent[] = []; if ('agentIds' in options) { const givenAgentsResults = await getAgentDocuments(esClient, options.agentIds); @@ -48,25 +44,29 @@ export async function updateAgentTags( } } } else if ('kuery' in options) { - return await processAgentsInBatches( - esClient, - { - kuery: options.kuery, - showInactive: true, - batchSize: options.batchSize, - }, - async (agents: Agent[], skipSuccess: boolean) => - await updateTagsBatch( - soClient, - esClient, - agents, - outgoingErrors, + const batchSize = options.batchSize ?? SO_SEARCH_LIMIT; + const res = await getAgentsByKuery(esClient, { + kuery: options.kuery, + showInactive: options.showInactive ?? false, + page: 1, + perPage: batchSize, + }); + if (res.total <= batchSize) { + givenAgents = res.agents; + } else { + return await new UpdateAgentTagsActionRunner( + esClient, + soClient, + { + ...options, + batchSize, + total: res.total, tagsToAdd, tagsToRemove, - undefined, - skipSuccess - ) - ); + }, + { pitId: await openPointInTime(esClient) } + ).runActionAsyncWithRetry(); + } } return await updateTagsBatch( @@ -74,57 +74,7 @@ export async function updateAgentTags( esClient, givenAgents, outgoingErrors, - tagsToAdd, - tagsToRemove, + { tagsToAdd, tagsToRemove }, 'agentIds' in options ? options.agentIds : undefined ); } - -async function updateTagsBatch( - soClient: SavedObjectsClientContract, - esClient: ElasticsearchClient, - givenAgents: Agent[], - outgoingErrors: Record<Agent['id'], Error>, - tagsToAdd: string[], - tagsToRemove: string[], - agentIds?: string[], - skipSuccess?: boolean -): Promise<{ items: BulkActionResult[] }> { - const errors: Record<Agent['id'], Error> = { ...outgoingErrors }; - - const filteredAgents = await filterHostedPolicies( - soClient, - givenAgents, - errors, - `Cannot modify tags on a hosted agent` - ); - - const getNewTags = (agent: Agent): string[] => { - const existingTags = agent.tags ?? []; - - if (tagsToAdd.length === 1 && tagsToRemove.length === 1) { - const removableTagIndex = existingTags.indexOf(tagsToRemove[0]); - if (removableTagIndex > -1) { - const newTags = uniq([ - ...existingTags.slice(0, removableTagIndex), - tagsToAdd[0], - ...existingTags.slice(removableTagIndex + 1), - ]); - return newTags; - } - } - return uniq(difference(existingTags, tagsToRemove).concat(tagsToAdd)); - }; - - await bulkUpdateAgents( - esClient, - filteredAgents.map((agent) => ({ - agentId: agent.id, - data: { - tags: getNewTags(agent), - }, - })) - ); - - return { items: errorsToResults(filteredAgents, errors, agentIds, skipSuccess) }; -} diff --git a/x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts b/x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts new file mode 100644 index 00000000000000..906566aee9f413 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/update_agent_tags_action_runner.ts @@ -0,0 +1,91 @@ +/* + * 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 type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/server'; + +import { difference, uniq } from 'lodash'; + +import type { Agent, BulkActionResult } from '../../types'; + +import { ActionRunner } from './action_runner'; + +import { errorsToResults, bulkUpdateAgents } from './crud'; +import { BulkActionTaskType } from './bulk_actions_resolver'; +import { filterHostedPolicies } from './filter_hosted_agents'; + +export class UpdateAgentTagsActionRunner extends ActionRunner { + protected async processAgents(agents: Agent[]): Promise<{ items: BulkActionResult[] }> { + return await updateTagsBatch( + this.soClient, + this.esClient, + agents, + {}, + { tagsToAdd: this.actionParams?.tagsToAdd, tagsToRemove: this.actionParams?.tagsToRemove }, + undefined, + true + ); + } + + protected getTaskType() { + return BulkActionTaskType.UPDATE_AGENT_TAGS_RETRY; + } + + protected getActionType() { + return 'UPDATE_TAGS'; + } +} + +export async function updateTagsBatch( + soClient: SavedObjectsClientContract, + esClient: ElasticsearchClient, + givenAgents: Agent[], + outgoingErrors: Record<Agent['id'], Error>, + options: { + tagsToAdd: string[]; + tagsToRemove: string[]; + }, + agentIds?: string[], + skipSuccess?: boolean +): Promise<{ items: BulkActionResult[] }> { + const errors: Record<Agent['id'], Error> = { ...outgoingErrors }; + + const filteredAgents = await filterHostedPolicies( + soClient, + givenAgents, + errors, + `Cannot modify tags on a hosted agent` + ); + + const getNewTags = (agent: Agent): string[] => { + const existingTags = agent.tags ?? []; + + if (options.tagsToAdd.length === 1 && options.tagsToRemove.length === 1) { + const removableTagIndex = existingTags.indexOf(options.tagsToRemove[0]); + if (removableTagIndex > -1) { + const newTags = uniq([ + ...existingTags.slice(0, removableTagIndex), + options.tagsToAdd[0], + ...existingTags.slice(removableTagIndex + 1), + ]); + return newTags; + } + } + return uniq(difference(existingTags, options.tagsToRemove).concat(options.tagsToAdd)); + }; + + await bulkUpdateAgents( + esClient, + filteredAgents.map((agent) => ({ + agentId: agent.id, + data: { + tags: getNewTags(agent), + }, + })) + ); + + return { items: errorsToResults(filteredAgents, errors, agentIds, skipSuccess) }; +} diff --git a/x-pack/plugins/fleet/server/services/agents/upgrade.ts b/x-pack/plugins/fleet/server/services/agents/upgrade.ts index 1083e8f728ee19..b6c50a3b5dc3c7 100644 --- a/x-pack/plugins/fleet/server/services/agents/upgrade.ts +++ b/x-pack/plugins/fleet/server/services/agents/upgrade.ts @@ -6,28 +6,18 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; -import moment from 'moment'; -import pMap from 'p-map'; -import uuid from 'uuid/v4'; -import type { Agent, BulkActionResult, FleetServerAgentAction, CurrentUpgrade } from '../../types'; -import { - AgentReassignmentError, - HostedAgentPolicyRestrictionRelatedError, - IngestManagerError, -} from '../../errors'; -import { isAgentUpgradeable } from '../../../common/services'; -import { appContextService } from '../app_context'; -import { AGENT_ACTIONS_INDEX, AGENT_ACTIONS_RESULTS_INDEX } from '../../../common'; +import type { Agent, BulkActionResult } from '../../types'; +import { AgentReassignmentError, HostedAgentPolicyRestrictionRelatedError } from '../../errors'; +import { SO_SEARCH_LIMIT } from '../../constants'; import { createAgentAction } from './actions'; import type { GetAgentsOptions } from './crud'; -import { errorsToResults, processAgentsInBatches } from './crud'; -import { getAgentDocuments, updateAgent, bulkUpdateAgents, getAgentPolicyForAgent } from './crud'; +import { openPointInTime } from './crud'; +import { getAgentsByKuery } from './crud'; +import { getAgentDocuments, updateAgent, getAgentPolicyForAgent } from './crud'; import { searchHitToAgent } from './helpers'; -import { getHostedPolicies, isHostedAgent } from './hosted_agent'; - -const MINIMUM_EXECUTION_DURATION_SECONDS = 1800; // 30m +import { UpgradeActionRunner, upgradeBatch } from './upgrade_action_runner'; function isMgetDoc(doc?: estypes.MgetResponseItem<unknown>): doc is estypes.GetGetResult { return Boolean(doc && 'found' in doc); @@ -83,7 +73,7 @@ export async function sendUpgradeAgentsActions( startTime?: string; batchSize?: number; } -) { +): Promise<{ items: BulkActionResult[]; actionId?: string }> { // Full set of agents const outgoingErrors: Record<Agent['id'], Error> = {}; let givenAgents: Agent[] = []; @@ -101,286 +91,28 @@ export async function sendUpgradeAgentsActions( } } } else if ('kuery' in options) { - const actionId = uuid(); - return await processAgentsInBatches( - esClient, - { - kuery: options.kuery, - showInactive: options.showInactive ?? false, - batchSize: options.batchSize, - }, - async (agents: Agent[], skipSuccess: boolean) => - await upgradeBatch( - soClient, - esClient, - agents, - outgoingErrors, - { ...options, actionId }, - skipSuccess - ) - ); - } - - return await upgradeBatch(soClient, esClient, givenAgents, outgoingErrors, options); -} - -async function upgradeBatch( - soClient: SavedObjectsClientContract, - esClient: ElasticsearchClient, - givenAgents: Agent[], - outgoingErrors: Record<Agent['id'], Error>, - options: ({ agents: Agent[] } | GetAgentsOptions) & { - actionId?: string; - version: string; - sourceUri?: string | undefined; - force?: boolean; - upgradeDurationSeconds?: number; - startTime?: string; - }, - skipSuccess?: boolean -): Promise<{ items: BulkActionResult[] }> { - const errors: Record<Agent['id'], Error> = { ...outgoingErrors }; - - const hostedPolicies = await getHostedPolicies(soClient, givenAgents); - - // results from getAgents with options.kuery '' (or even 'active:false') may include hosted agents - // filter them out unless options.force - const agentsToCheckUpgradeable = - 'kuery' in options && !options.force - ? givenAgents.filter((agent: Agent) => !isHostedAgent(hostedPolicies, agent)) - : givenAgents; - - const kibanaVersion = appContextService.getKibanaVersion(); - const upgradeableResults = await Promise.allSettled( - agentsToCheckUpgradeable.map(async (agent) => { - // Filter out agents currently unenrolling, unenrolled, or not upgradeable b/c of version check - const isNotAllowed = - !options.force && !isAgentUpgradeable(agent, kibanaVersion, options.version); - if (isNotAllowed) { - throw new IngestManagerError(`${agent.id} is not upgradeable`); - } - - if (!options.force && isHostedAgent(hostedPolicies, agent)) { - throw new HostedAgentPolicyRestrictionRelatedError( - `Cannot upgrade agent in hosted agent policy ${agent.policy_id}` - ); - } - return agent; - }) - ); - - // Filter & record errors from results - const agentsToUpdate = upgradeableResults.reduce<Agent[]>((agents, result, index) => { - if (result.status === 'fulfilled') { - agents.push(result.value); + const batchSize = options.batchSize ?? SO_SEARCH_LIMIT; + const res = await getAgentsByKuery(esClient, { + kuery: options.kuery, + showInactive: options.showInactive ?? false, + page: 1, + perPage: batchSize, + }); + if (res.total <= batchSize) { + givenAgents = res.agents; } else { - const id = givenAgents[index].id; - errors[id] = result.reason; - } - return agents; - }, []); - - // Create upgrade action for each agent - const now = new Date().toISOString(); - const data = { - version: options.version, - source_uri: options.sourceUri, - }; - - const rollingUpgradeOptions = getRollingUpgradeOptions( - options?.startTime, - options.upgradeDurationSeconds - ); - - await createAgentAction(esClient, { - id: options.actionId, - created_at: now, - data, - ack_data: data, - type: 'UPGRADE', - agents: agentsToUpdate.map((agent) => agent.id), - ...rollingUpgradeOptions, - }); - - await bulkUpdateAgents( - esClient, - agentsToUpdate.map((agent) => ({ - agentId: agent.id, - data: { - upgrade_started_at: now, - upgrade_status: 'started', - }, - })) - ); - - return { - items: errorsToResults( - givenAgents, - errors, - 'agentIds' in options ? options.agentIds : undefined, - skipSuccess - ), - }; -} - -/** - * Return current bulk upgrades (non completed or cancelled) - */ -export async function getCurrentBulkUpgrades( - esClient: ElasticsearchClient, - now = new Date().toISOString() -): Promise<CurrentUpgrade[]> { - // Fetch all non expired actions - const [_upgradeActions, cancelledActionIds] = await Promise.all([ - _getUpgradeActions(esClient, now), - _getCancelledActionId(esClient, now), - ]); - - let upgradeActions = _upgradeActions.filter( - (action) => cancelledActionIds.indexOf(action.actionId) < 0 - ); - - // Fetch acknowledged result for every upgrade action - upgradeActions = await pMap( - upgradeActions, - async (upgradeAction) => { - const { count } = await esClient.count({ - index: AGENT_ACTIONS_RESULTS_INDEX, - ignore_unavailable: true, - query: { - bool: { - must: [ - { - term: { - action_id: upgradeAction.actionId, - }, - }, - ], - }, + return await new UpgradeActionRunner( + esClient, + soClient, + { + ...options, + batchSize, + total: res.total, }, - }); - - return { - ...upgradeAction, - nbAgentsAck: count, - complete: upgradeAction.nbAgents <= count, - }; - }, - { concurrency: 20 } - ); - - upgradeActions = upgradeActions.filter((action) => !action.complete); - - return upgradeActions; -} - -async function _getCancelledActionId( - esClient: ElasticsearchClient, - now = new Date().toISOString() -) { - const res = await esClient.search<FleetServerAgentAction>({ - index: AGENT_ACTIONS_INDEX, - ignore_unavailable: true, - query: { - bool: { - must: [ - { - term: { - type: 'CANCEL', - }, - }, - { - exists: { - field: 'agents', - }, - }, - { - range: { - expiration: { gte: now }, - }, - }, - ], - }, - }, - }); - - return res.hits.hits.map((hit) => hit._source?.data?.target_id as string); -} - -async function _getUpgradeActions(esClient: ElasticsearchClient, now = new Date().toISOString()) { - const res = await esClient.search<FleetServerAgentAction>({ - index: AGENT_ACTIONS_INDEX, - ignore_unavailable: true, - query: { - bool: { - must: [ - { - term: { - type: 'UPGRADE', - }, - }, - { - exists: { - field: 'agents', - }, - }, - { - range: { - expiration: { gte: now }, - }, - }, - ], - }, - }, - }); - - return Object.values( - res.hits.hits.reduce((acc, hit) => { - if (!hit._source || !hit._source.action_id) { - return acc; - } - - if (!acc[hit._source.action_id]) { - acc[hit._source.action_id] = { - actionId: hit._source.action_id, - nbAgents: 0, - complete: false, - nbAgentsAck: 0, - version: hit._source.data?.version as string, - startTime: hit._source?.start_time, - }; - } - - acc[hit._source.action_id].nbAgents += hit._source.agents?.length ?? 0; + { pitId: await openPointInTime(esClient) } + ).runActionAsyncWithRetry(); + } + } - return acc; - }, {} as { [k: string]: CurrentUpgrade }) - ); + return await upgradeBatch(soClient, esClient, givenAgents, outgoingErrors, options); } - -const getRollingUpgradeOptions = (startTime?: string, upgradeDurationSeconds?: number) => { - const now = new Date().toISOString(); - // Perform a rolling upgrade - if (upgradeDurationSeconds) { - return { - start_time: startTime ?? now, - minimum_execution_duration: MINIMUM_EXECUTION_DURATION_SECONDS, - expiration: moment(startTime ?? now) - .add(upgradeDurationSeconds, 'seconds') - .toISOString(), - }; - } - // Schedule without rolling upgrade (Immediately after start_time) - if (startTime && !upgradeDurationSeconds) { - return { - start_time: startTime ?? now, - minimum_execution_duration: MINIMUM_EXECUTION_DURATION_SECONDS, - expiration: moment(startTime) - .add(MINIMUM_EXECUTION_DURATION_SECONDS, 'seconds') - .toISOString(), - }; - } else { - // Regular bulk upgrade (non scheduled, non rolling) - return {}; - } -}; diff --git a/x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts b/x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts new file mode 100644 index 00000000000000..ca2bd6a996d678 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/agents/upgrade_action_runner.ts @@ -0,0 +1,180 @@ +/* + * 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 type { SavedObjectsClientContract, ElasticsearchClient } from '@kbn/core/server'; + +import moment from 'moment'; + +import { isAgentUpgradeable } from '../../../common/services'; + +import type { Agent, BulkActionResult } from '../../types'; + +import { HostedAgentPolicyRestrictionRelatedError, IngestManagerError } from '../../errors'; + +import { appContextService } from '../app_context'; + +import { ActionRunner } from './action_runner'; + +import type { GetAgentsOptions } from './crud'; +import { errorsToResults, bulkUpdateAgents } from './crud'; +import { createAgentAction } from './actions'; +import { getHostedPolicies, isHostedAgent } from './hosted_agent'; +import { BulkActionTaskType } from './bulk_actions_resolver'; + +export class UpgradeActionRunner extends ActionRunner { + protected async processAgents(agents: Agent[]): Promise<{ items: BulkActionResult[] }> { + return await upgradeBatch( + this.soClient, + this.esClient, + agents, + {}, + this.actionParams! as any, + true + ); + } + + protected getTaskType() { + return BulkActionTaskType.UPGRADE_RETRY; + } + + protected getActionType() { + return 'UPGRADE'; + } +} + +export async function upgradeBatch( + soClient: SavedObjectsClientContract, + esClient: ElasticsearchClient, + givenAgents: Agent[], + outgoingErrors: Record<Agent['id'], Error>, + options: ({ agents: Agent[] } | GetAgentsOptions) & { + actionId?: string; + version: string; + sourceUri?: string | undefined; + force?: boolean; + upgradeDurationSeconds?: number; + startTime?: string; + total?: number; + }, + skipSuccess?: boolean +): Promise<{ items: BulkActionResult[] }> { + const errors: Record<Agent['id'], Error> = { ...outgoingErrors }; + + const hostedPolicies = await getHostedPolicies(soClient, givenAgents); + + // results from getAgents with options.kuery '' (or even 'active:false') may include hosted agents + // filter them out unless options.force + const agentsToCheckUpgradeable = + 'kuery' in options && !options.force + ? givenAgents.filter((agent: Agent) => !isHostedAgent(hostedPolicies, agent)) + : givenAgents; + + const kibanaVersion = appContextService.getKibanaVersion(); + const upgradeableResults = await Promise.allSettled( + agentsToCheckUpgradeable.map(async (agent) => { + // Filter out agents currently unenrolling, unenrolled, or not upgradeable b/c of version check + const isNotAllowed = + !options.force && !isAgentUpgradeable(agent, kibanaVersion, options.version); + if (isNotAllowed) { + throw new IngestManagerError(`${agent.id} is not upgradeable`); + } + + if (!options.force && isHostedAgent(hostedPolicies, agent)) { + throw new HostedAgentPolicyRestrictionRelatedError( + `Cannot upgrade agent in hosted agent policy ${agent.policy_id}` + ); + } + return agent; + }) + ); + + // Filter & record errors from results + const agentsToUpdate = upgradeableResults.reduce<Agent[]>((agents, result, index) => { + if (result.status === 'fulfilled') { + agents.push(result.value); + } else { + const id = givenAgents[index].id; + errors[id] = result.reason; + } + return agents; + }, []); + + // Create upgrade action for each agent + const now = new Date().toISOString(); + const data = { + version: options.version, + source_uri: options.sourceUri, + }; + + const rollingUpgradeOptions = getRollingUpgradeOptions( + options?.startTime, + options.upgradeDurationSeconds + ); + + await createAgentAction(esClient, { + id: options.actionId, + created_at: now, + data, + ack_data: data, + type: 'UPGRADE', + total: options.total, + agents: agentsToUpdate.map((agent) => agent.id), + ...rollingUpgradeOptions, + }); + + await bulkUpdateAgents( + esClient, + agentsToUpdate.map((agent) => ({ + agentId: agent.id, + data: { + upgrade_started_at: now, + upgrade_status: 'started', + }, + })) + ); + + return { + items: errorsToResults( + givenAgents, + errors, + 'agentIds' in options ? options.agentIds : undefined, + skipSuccess + ), + }; +} + +const MINIMUM_EXECUTION_DURATION_SECONDS = 60 * 60 * 2; // 2h + +const getRollingUpgradeOptions = (startTime?: string, upgradeDurationSeconds?: number) => { + const now = new Date().toISOString(); + // Perform a rolling upgrade + if (upgradeDurationSeconds) { + return { + start_time: startTime ?? now, + minimum_execution_duration: Math.min( + MINIMUM_EXECUTION_DURATION_SECONDS, + upgradeDurationSeconds + ), + expiration: moment(startTime ?? now) + .add(upgradeDurationSeconds, 'seconds') + .toISOString(), + }; + } + // Schedule without rolling upgrade (Immediately after start_time) + if (startTime && !upgradeDurationSeconds) { + return { + start_time: startTime ?? now, + minimum_execution_duration: MINIMUM_EXECUTION_DURATION_SECONDS, + expiration: moment(startTime) + .add(MINIMUM_EXECUTION_DURATION_SECONDS, 'seconds') + .toISOString(), + }; + } else { + // Regular bulk upgrade (non scheduled, non rolling) + return {}; + } +}; diff --git a/x-pack/plugins/fleet/server/services/app_context.ts b/x-pack/plugins/fleet/server/services/app_context.ts index 86f9408bef3f3f..3257f3e969ec80 100644 --- a/x-pack/plugins/fleet/server/services/app_context.ts +++ b/x-pack/plugins/fleet/server/services/app_context.ts @@ -41,6 +41,8 @@ import type { import type { FleetAppContext } from '../plugin'; import type { TelemetryEventsSender } from '../telemetry/sender'; +import type { BulkActionsResolver } from './agents'; + class AppContextService { private encryptedSavedObjects: EncryptedSavedObjectsClient | undefined; private encryptedSavedObjectsSetup: EncryptedSavedObjectsPluginSetup | undefined; @@ -61,6 +63,7 @@ class AppContextService { private externalCallbacks: ExternalCallbacksStorage = new Map(); private telemetryEventsSender: TelemetryEventsSender | undefined; private savedObjectsTagging: SavedObjectTaggingStart | undefined; + private bulkActionsResolver: BulkActionsResolver | undefined; public start(appContext: FleetAppContext) { this.data = appContext.data; @@ -79,6 +82,7 @@ class AppContextService { this.httpSetup = appContext.httpSetup; this.telemetryEventsSender = appContext.telemetryEventsSender; this.savedObjectsTagging = appContext.savedObjectsTagging; + this.bulkActionsResolver = appContext.bulkActionsResolver; if (appContext.config$) { this.config$ = appContext.config$; @@ -228,6 +232,10 @@ class AppContextService { public getTelemetryEventsSender() { return this.telemetryEventsSender; } + + public getBulkActionsResolver() { + return this.bulkActionsResolver; + } } export const appContextService = new AppContextService(); diff --git a/x-pack/plugins/fleet/server/types/index.tsx b/x-pack/plugins/fleet/server/types/index.tsx index be923a9fdaa6fc..fd0cee334cc508 100644 --- a/x-pack/plugins/fleet/server/types/index.tsx +++ b/x-pack/plugins/fleet/server/types/index.tsx @@ -12,6 +12,7 @@ export type { AgentStatus, AgentType, AgentAction, + ActionStatus, CurrentUpgrade, PackagePolicy, PackagePolicyInput, diff --git a/x-pack/test/fleet_api_integration/apis/agents/reassign.ts b/x-pack/test/fleet_api_integration/apis/agents/reassign.ts index 7c97ff5b79bf9a..746a2fcda1ba17 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/reassign.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/reassign.ts @@ -199,7 +199,7 @@ export default function (providerContext: FtrProviderContext) { }); it('should bulk reassign multiple agents by kuery in batches', async () => { - const { body: unenrolledBody } = await supertest + const { body } = await supertest .post(`/api/fleet/agents/bulk_reassign`) .set('kbn-xsrf', 'xxx') .send({ @@ -209,17 +209,37 @@ export default function (providerContext: FtrProviderContext) { }) .expect(200); - expect(unenrolledBody).to.eql({ - agent1: { success: true }, - agent2: { success: true }, - agent3: { success: true }, - agent4: { success: true }, - }); + const actionId = body.actionId; - const { body } = await supertest.get(`/api/fleet/agents`).set('kbn-xsrf', 'xxx'); - expect(body.total).to.eql(4); - body.items.forEach((agent: any) => { - expect(agent.policy_id).to.eql('policy2'); + const verifyActionResult = async () => { + const { body: result } = await supertest.get(`/api/fleet/agents`).set('kbn-xsrf', 'xxx'); + expect(result.total).to.eql(4); + result.items.forEach((agent: any) => { + expect(agent.policy_id).to.eql('policy2'); + }); + }; + + await new Promise((resolve, reject) => { + let attempts = 0; + const intervalId = setInterval(async () => { + if (attempts > 2) { + clearInterval(intervalId); + reject('action timed out'); + } + ++attempts; + const { + body: { items: actionStatuses }, + } = await supertest.get(`/api/fleet/agents/action_status`).set('kbn-xsrf', 'xxx'); + + const action = actionStatuses.find((a: any) => a.actionId === actionId); + if (action && action.nbAgentsActioned === action.nbAgentsActionCreated) { + clearInterval(intervalId); + await verifyActionResult(); + resolve({}); + } + }, 1000); + }).catch((e) => { + throw e; }); }); diff --git a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts index 93d0a58b848df1..3956dcafad7052 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts @@ -198,26 +198,40 @@ export default function (providerContext: FtrProviderContext) { expect(body.total).to.eql(0); }); - it('/agents/bulk_unenroll should allow to unenroll multiple agents by kuery in batches', async () => { - const { body: unenrolledBody } = await supertest + it('/agents/bulk_unenroll should allow to unenroll multiple agents by kuery in batches async', async () => { + const { body } = await supertest .post(`/api/fleet/agents/bulk_unenroll`) .set('kbn-xsrf', 'xxx') .send({ agents: 'active: true', - revoke: true, + revoke: false, batchSize: 2, }) .expect(200); - expect(unenrolledBody).to.eql({ - agent1: { success: true }, - agent2: { success: true }, - agent3: { success: true }, - agent4: { success: true }, + const actionId = body.actionId; + + await new Promise((resolve, reject) => { + let attempts = 0; + const intervalId = setInterval(async () => { + if (attempts > 2) { + clearInterval(intervalId); + reject('action timed out'); + } + ++attempts; + const { + body: { items: actionStatuses }, + } = await supertest.get(`/api/fleet/agents/action_status`).set('kbn-xsrf', 'xxx'); + + const action = actionStatuses.find((a: any) => a.actionId === actionId); + if (action && action.nbAgentsActioned === action.nbAgentsActionCreated) { + clearInterval(intervalId); + resolve({}); + } + }, 1000); + }).catch((e) => { + throw e; }); - - const { body } = await supertest.get(`/api/fleet/agents`); - expect(body.total).to.eql(0); }); }); } diff --git a/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts b/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts index 2de75be2e50b00..afe9f8d677d354 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/update_agent_tags.ts @@ -88,7 +88,7 @@ export default function (providerContext: FtrProviderContext) { }); it('should bulk update tags of multiple agents by kuery in batches', async () => { - const { body: updatedBody } = await supertest + await supertest .post(`/api/fleet/agents/bulk_update_agent_tags`) .set('kbn-xsrf', 'xxx') .send({ @@ -99,18 +99,18 @@ export default function (providerContext: FtrProviderContext) { }) .expect(200); - expect(updatedBody).to.eql({ - agent1: { success: true }, - agent2: { success: true }, - agent3: { success: true }, - agent4: { success: true }, - }); - - const { body } = await supertest.get(`/api/fleet/agents`).set('kbn-xsrf', 'xxx'); - expect(body.total).to.eql(4); - body.items.forEach((agent: any) => { - expect(agent.tags.includes('newTag')).to.be(true); - expect(agent.tags.includes('existingTag')).to.be(false); + await new Promise((resolve, reject) => { + setTimeout(async () => { + const { body } = await supertest.get(`/api/fleet/agents`).set('kbn-xsrf', 'xxx'); + expect(body.total).to.eql(4); + body.items.forEach((agent: any) => { + expect(agent.tags.includes('newTag')).to.be(true); + expect(agent.tags.includes('existingTag')).to.be(false); + }); + resolve({}); + }, 2000); + }).catch((e) => { + throw e; }); }); diff --git a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts index 9b0a6586e1c25e..b842f89c8ac644 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/upgrade.ts @@ -540,7 +540,7 @@ export default function (providerContext: FtrProviderContext) { expect(typeof agent2data.body.item.upgrade_started_at).to.be('undefined'); }); - it('should bulk upgrade multiple agents by kuery in batches', async () => { + it('should bulk upgrade multiple agents by kuery in batches async', async () => { await es.update({ id: 'agent1', refresh: 'wait_for', @@ -557,17 +557,12 @@ export default function (providerContext: FtrProviderContext) { index: AGENTS_INDEX, body: { doc: { - local_metadata: { - elastic: { - agent: { upgradeable: false, version: '0.0.0' }, - }, - }, - upgrade_started_at: undefined, + local_metadata: { elastic: { agent: { upgradeable: true, version: '0.0.0' } } }, }, }, }); - const { body: unenrolledBody } = await supertest + const { body } = await supertest .post(`/api/fleet/agents/bulk_upgrade`) .set('kbn-xsrf', 'xxx') .send({ @@ -577,12 +572,38 @@ export default function (providerContext: FtrProviderContext) { }) .expect(200); - expect(unenrolledBody).to.eql({ - agent4: { success: false, error: 'agent4 is not upgradeable' }, - agent3: { success: false, error: 'agent3 is not upgradeable' }, - agent2: { success: false, error: 'agent2 is not upgradeable' }, - agent1: { success: true }, - agentWithFS: { success: false, error: 'agentWithFS is not upgradeable' }, + const actionId = body.actionId; + + const verifyActionResult = async () => { + const [agent1data, agent2data] = await Promise.all([ + supertest.get(`/api/fleet/agents/agent1`).set('kbn-xsrf', 'xxx'), + supertest.get(`/api/fleet/agents/agent2`).set('kbn-xsrf', 'xxx'), + ]); + expect(typeof agent1data.body.item.upgrade_started_at).to.be('string'); + expect(typeof agent2data.body.item.upgrade_started_at).to.be('string'); + }; + + await new Promise((resolve, reject) => { + let attempts = 0; + const intervalId = setInterval(async () => { + if (attempts > 2) { + clearInterval(intervalId); + reject('action timed out'); + } + ++attempts; + const { + body: { items: actionStatuses }, + } = await supertest.get(`/api/fleet/agents/action_status`).set('kbn-xsrf', 'xxx'); + const action = actionStatuses.find((a: any) => a.actionId === actionId); + // 2 upgradeable + if (action && action.nbAgentsActionCreated === 2) { + clearInterval(intervalId); + await verifyActionResult(); + resolve({}); + } + }, 1000); + }).catch((e) => { + throw e; }); }); From bcf8c79bb3c39f68cf96abc634c95392504c1233 Mon Sep 17 00:00:00 2001 From: Matthew Kime <matt@mattki.me> Date: Mon, 12 Sep 2022 08:43:22 -0500 Subject: [PATCH 061/144] [data view field editor] Composite runtime field editor (#136954) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial commit * [Runtime field editor] Composite runtime in Kibana Data Views (#110226) * Apply updates from feature branch * Fix TS issues * Fix TS issue * Fix TS issue * Fix jest tests * fix jest tests * fix integration test * fix delete error test * partial progress * partial progress * remove mistaken change * fix import * remove unused translation * partial progress * merge * use preview api * cleanup * use specific index instead of index pattern * fix jest test * one less any * setting type on composite subfields is roughly working * partial progress * setState not working * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * partial progress * working but a bit wonky * merge * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * fix handing of field types, remove some console.log statements * fix initial type for subfields * fix subfield type updates, rename some vars * fix breakage from bad merge * fix types * type fixes * cleanup * i18n fix * i18n fix * i18n fix * comment cleanup * remove unused var * add code comment * remove comments * fix jest test * add start of functional test * functional test: * composite subfield preview * add functional test * functional tests * functional tests * rendering improvements * functional tests * functional tests * add jest test * add jest test * move to observables * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * cleanup * better use of form lib * type fixes * cleanup * add refresh button * remove ts ignore * improve dev docs * internationalize text * type fix * delete should warn regarding subfields * typescript fix * redraws of FieldEditor would reset diff state. This fixes it. * add placeholder text to code editor * hook cleanup * add getFieldPreviewChanges jest test * add getFieldPreviewChanges jest test * keep parent name in sync with preview when changed during script update * fix test * move subfields to observables * fix jest tests * fix jest tests * fix save after field type change to composite * previewFields to behaviorSubject * fix test Co-authored-by: Sébastien Loix <sabee77@gmail.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Sébastien Loix <sebastien.loix@elastic.co> --- .../client_integration/field_editor.test.tsx | 12 +- .../field_editor_flyout_content.test.ts | 5 +- .../field_editor_flyout_preview.test.ts | 44 +++ .../helpers/setup_environment.tsx | 7 +- .../components/delete_field_provider.tsx | 7 + .../field_editor/composite_editor.tsx | 120 +++++++++ .../components/field_editor/constants.ts | 10 +- .../components/field_editor/field_detail.tsx | 117 ++++++++ .../components/field_editor/field_editor.tsx | 253 +++++++++--------- .../field_editor/form_fields/format_field.tsx | 9 +- .../field_editor/form_fields/script_field.tsx | 5 +- .../field_editor/form_fields/type_field.tsx | 23 +- .../components/field_editor/form_schema.ts | 3 + .../components/field_editor/lib.test.ts | 67 +++++ .../public/components/field_editor/lib.ts | 74 ++++- .../public/components/field_editor/types.ts | 18 ++ .../components/field_editor_context.tsx | 22 +- .../field_editor_flyout_content.tsx | 26 +- .../field_editor_flyout_content_container.tsx | 111 +++++--- .../field_format_editor/format_editor.tsx | 2 +- .../components/field_format_editor/index.ts | 2 + .../components/preview/field_preview.tsx | 29 +- .../preview/field_preview_context.tsx | 173 ++++++++++-- .../public/components/preview/types.ts | 31 ++- .../public/components/utils.ts | 17 ++ .../data_view_field_editor/public/index.ts | 11 +- .../public/lib/serialization.ts | 6 +- .../public/open_delete_modal.tsx | 38 +++ .../public/open_editor.tsx | 73 ++++- .../public/shared_imports.ts | 12 +- .../data_view_field_editor/public/types.ts | 44 +-- .../server/routes/field_preview.ts | 1 + .../edit_index_pattern/edit_index_pattern.tsx | 11 +- .../table/__snapshots__/table.test.tsx.snap | 6 +- .../components/table/table.tsx | 49 +++- .../indexed_fields_table.test.tsx | 7 +- .../indexed_fields_table.tsx | 66 ++++- .../edit_index_pattern/tabs/tabs.tsx | 5 + .../common/data_views/data_view.test.ts | 9 +- .../common/data_views/data_views.ts | 9 +- .../data_views/common/data_views/utils.ts | 4 +- src/plugins/data_views/common/index.ts | 3 +- src/plugins/data_views/common/types.ts | 29 +- src/plugins/data_views/public/index.ts | 1 + .../management/_runtime_fields_composite.ts | 90 +++++++ test/functional/apps/management/index.ts | 1 + test/functional/page_objects/settings_page.ts | 31 +++ .../components/fields_browser/index.test.tsx | 12 +- .../components/fields_browser/index.tsx | 39 +-- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 52 files changed, 1397 insertions(+), 350 deletions(-) create mode 100644 src/plugins/data_view_field_editor/public/components/field_editor/composite_editor.tsx create mode 100644 src/plugins/data_view_field_editor/public/components/field_editor/field_detail.tsx create mode 100644 src/plugins/data_view_field_editor/public/components/field_editor/lib.test.ts create mode 100644 src/plugins/data_view_field_editor/public/components/field_editor/types.ts create mode 100644 src/plugins/data_view_field_editor/public/components/utils.ts create mode 100644 test/functional/apps/management/_runtime_fields_composite.ts diff --git a/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor.test.tsx b/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor.test.tsx index 521d7aff8f976b..50dce256792528 100644 --- a/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor.test.tsx +++ b/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor.test.tsx @@ -112,7 +112,7 @@ describe('<FieldEditor />', () => { expect(lastState.submit).toBeDefined(); const { data: formData } = await submitFormAndGetData(lastState); - expect(formData).toEqual(field); + expect(formData).toEqual({ ...field, format: null }); // Make sure that both isValid and isSubmitted state are now "true" lastState = getLastStateUpdate(); @@ -128,7 +128,10 @@ describe('<FieldEditor />', () => { onChange, }, { - namesNotAllowed: existingFields, + namesNotAllowed: { + fields: existingFields, + runtimeComposites: [], + }, existingConcreteFields: [], fieldTypeToProcess: 'runtime', } @@ -165,7 +168,10 @@ describe('<FieldEditor />', () => { onChange, }, { - namesNotAllowed: existingRuntimeFieldNames, + namesNotAllowed: { + fields: existingRuntimeFieldNames, + runtimeComposites: [], + }, existingConcreteFields: [], fieldTypeToProcess: 'runtime', } diff --git a/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_content.test.ts b/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_content.test.ts index 63eca247cca6f8..51cd024f0b53e0 100644 --- a/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_content.test.ts +++ b/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_content.test.ts @@ -88,7 +88,7 @@ describe('<FieldEditorFlyoutContent />', () => { expect(onSave).toHaveBeenCalled(); const fieldReturned = onSave.mock.calls[onSave.mock.calls.length - 1][0]; - expect(fieldReturned).toEqual(field); + expect(fieldReturned).toEqual({ ...field, format: null }); }); test('should accept an onCancel prop', async () => { @@ -149,6 +149,7 @@ describe('<FieldEditorFlyoutContent />', () => { name: 'someName', type: 'keyword', // default to keyword script: { source: 'echo("hello")' }, + format: null, }); // Change the type and make sure it is forwarded @@ -165,6 +166,7 @@ describe('<FieldEditorFlyoutContent />', () => { name: 'someName', type: 'date', script: { source: 'echo("hello")' }, + format: null, }); }); @@ -202,6 +204,7 @@ describe('<FieldEditorFlyoutContent />', () => { name: 'someName', type: 'keyword', script: { source: 'echo("hello")' }, + format: null, }); }); }); diff --git a/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_preview.test.ts b/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_preview.test.ts index 5dd0045ab5d686..8659e12909763e 100644 --- a/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_preview.test.ts +++ b/src/plugins/data_view_field_editor/__jest__/client_integration/field_editor_flyout_preview.test.ts @@ -813,4 +813,48 @@ describe('Field editor Preview panel', () => { expect(exists('previewNotAvailableCallout')).toBe(true); }); }); + + describe('composite runtime field', () => { + test('should display composite editor when composite type is selected', async () => { + testBed = await setup(); + const { + exists, + actions: { fields, waitForUpdates }, + } = testBed; + fields.updateType('composite', 'Composite'); + await waitForUpdates(); + expect(exists('compositeEditor')).toBe(true); + }); + + test('should show composite field types and update appropriately', async () => { + httpRequestsMockHelpers.setFieldPreviewResponse({ values: { 'composite_field.a': [1] } }); + testBed = await setup(); + const { + exists, + actions: { fields, waitForUpdates }, + } = testBed; + await fields.updateType('composite', 'Composite'); + await fields.updateScript("emit('a',1)"); + await waitForUpdates(); + expect(exists('typeField_0')).toBe(true); + + // increase the number of fields + httpRequestsMockHelpers.setFieldPreviewResponse({ + values: { 'composite_field.a': [1], 'composite_field.b': [1] }, + }); + await fields.updateScript("emit('a',1); emit('b',1)"); + await waitForUpdates(); + expect(exists('typeField_0')).toBe(true); + expect(exists('typeField_1')).toBe(true); + + // decrease the number of fields + httpRequestsMockHelpers.setFieldPreviewResponse({ + values: { 'composite_field.a': [1] }, + }); + await fields.updateScript("emit('a',1)"); + await waitForUpdates(); + expect(exists('typeField_0')).toBe(true); + expect(exists('typeField_1')).toBe(false); + }); + }); }); diff --git a/src/plugins/data_view_field_editor/__jest__/client_integration/helpers/setup_environment.tsx b/src/plugins/data_view_field_editor/__jest__/client_integration/helpers/setup_environment.tsx index 9979e96261e7be..4f7cc3e57a9753 100644 --- a/src/plugins/data_view_field_editor/__jest__/client_integration/helpers/setup_environment.tsx +++ b/src/plugins/data_view_field_editor/__jest__/client_integration/helpers/setup_environment.tsx @@ -12,7 +12,7 @@ import './jest.mocks'; import React, { FunctionComponent } from 'react'; import { merge } from 'lodash'; -import { defer } from 'rxjs'; +import { defer, BehaviorSubject } from 'rxjs'; import { notificationServiceMock, uiSettingsServiceMock } from '@kbn/core/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { fieldFormatsMock as fieldFormats } from '@kbn/field-formats-plugin/common/mocks'; @@ -21,6 +21,7 @@ import { FieldEditorProvider, Context } from '../../../public/components/field_e import { FieldPreviewProvider } from '../../../public/components/preview'; import { initApi, ApiService } from '../../../public/lib'; import { init as initHttpRequests } from './http_requests'; +import { RuntimeFieldSubFields } from '../../../public/shared_imports'; const dataStart = dataPluginMock.createStartContract(); const { search } = dataStart; @@ -124,7 +125,7 @@ export const WithFieldEditorDependencies = uiSettings: uiSettingsServiceMock.createStartContract(), fieldTypeToProcess: 'runtime', existingConcreteFields: [], - namesNotAllowed: [], + namesNotAllowed: { fields: [], runtimeComposites: [] }, links: { runtimePainless: 'https://elastic.co', }, @@ -138,6 +139,8 @@ export const WithFieldEditorDependencies = getById: () => undefined, }, fieldFormats, + fieldName$: new BehaviorSubject(''), + subfields$: new BehaviorSubject<RuntimeFieldSubFields | undefined>(undefined), }; const mergedDependencies = merge({}, dependencies, overridingDependencies); diff --git a/src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx b/src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx index 9a960674e061e8..fc09b860f705ae 100644 --- a/src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx +++ b/src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx @@ -15,7 +15,14 @@ import { CloseEditor } from '../types'; type DeleteFieldFunc = (fieldName: string | string[]) => void; export interface Props { children: (deleteFieldHandler: DeleteFieldFunc) => React.ReactNode; + /** + * Data view of fields to be deleted + */ dataView: DataView; + /** + * Callback fired when fields are deleted + * @param fieldNames - the names of the deleted fields + */ onDelete?: (fieldNames: string[]) => void; } diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/composite_editor.tsx b/src/plugins/data_view_field_editor/public/components/field_editor/composite_editor.tsx new file mode 100644 index 00000000000000..49761aa1228440 --- /dev/null +++ b/src/plugins/data_view_field_editor/public/components/field_editor/composite_editor.tsx @@ -0,0 +1,120 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { + EuiNotificationBadge, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, + EuiFieldText, + EuiComboBox, + EuiFormRow, + EuiButtonEmpty, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import useObservable from 'react-use/lib/useObservable'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { ScriptField } from './form_fields'; +import { useFieldEditorContext } from '../field_editor_context'; +import { RUNTIME_FIELD_OPTIONS_PRIMITIVE } from './constants'; +import { valueToComboBoxOption } from './lib'; +import { RuntimePrimitiveTypes } from '../../shared_imports'; + +export interface CompositeEditorProps { + onReset: () => void; +} + +export const CompositeEditor = ({ onReset }: CompositeEditorProps) => { + const { links, existingConcreteFields, subfields$ } = useFieldEditorContext(); + const subfields = useObservable(subfields$) || {}; + + return ( + <div data-test-subj="compositeEditor"> + <ScriptField + existingConcreteFields={existingConcreteFields} + links={links} + placeholder={"emit('field_name', 'hello world');"} + /> + <EuiSpacer size="xl" /> + <> + <EuiFlexGroup gutterSize="s" alignItems="center" justifyContent="spaceBetween"> + <EuiFlexGroup gutterSize="s" alignItems="center"> + <EuiFlexItem grow={false}> + <EuiText size="s"> + <FormattedMessage + id="indexPatternFieldEditor.editor.compositeFieldsCount" + defaultMessage="Generated fields" + /> + </EuiText> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <EuiNotificationBadge color="subdued"> + {Object.entries(subfields).length} + </EuiNotificationBadge> + </EuiFlexItem> + </EuiFlexGroup> + <EuiFlexItem grow={false}> + <EuiButtonEmpty flush="right" iconType="refresh" onClick={onReset}> + <FormattedMessage + id="indexPatternFieldEditor.editor.compositeRefreshTypes" + defaultMessage="Reset" + /> + </EuiButtonEmpty> + </EuiFlexItem> + </EuiFlexGroup> + {Object.entries(subfields).map(([key, itemValue], idx) => { + return ( + <div> + <EuiFlexGroup gutterSize="s"> + <EuiFlexItem> + <EuiFieldText value={key} disabled={true} /> + </EuiFlexItem> + <EuiFlexItem> + <EuiFormRow fullWidth> + <EuiComboBox + placeholder={i18n.translate( + 'indexPatternFieldEditor.editor.form.runtimeType.placeholderLabel', + { + defaultMessage: 'Select a type', + } + )} + singleSelection={{ asPlainText: true }} + options={RUNTIME_FIELD_OPTIONS_PRIMITIVE} + selectedOptions={[valueToComboBoxOption(itemValue.type)!]} + onChange={(newValue) => { + if (newValue.length === 0) { + // Don't allow clearing the type. One must always be selected + return; + } + // update the type for the given field + subfields[key] = { type: newValue[0].value! as RuntimePrimitiveTypes }; + + subfields$.next({ ...subfields }); + }} + isClearable={false} + data-test-subj={`typeField_${idx}`} + aria-label={i18n.translate( + 'indexPatternFieldEditor.editor.form.typeSelectAriaLabel', + { + defaultMessage: 'Type select', + } + )} + fullWidth + /> + </EuiFormRow> + </EuiFlexItem> + </EuiFlexGroup> + </div> + ); + })} + </> + </div> + ); +}; diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/constants.ts b/src/plugins/data_view_field_editor/public/components/field_editor/constants.ts index e262d3ecbfe459..b8bf2673ac3bd9 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor/constants.ts +++ b/src/plugins/data_view_field_editor/public/components/field_editor/constants.ts @@ -9,7 +9,7 @@ import type { EuiComboBoxOptionOption } from '@elastic/eui'; import { RuntimeType } from '../../shared_imports'; -export const RUNTIME_FIELD_OPTIONS: Array<EuiComboBoxOptionOption<RuntimeType>> = [ +export const RUNTIME_FIELD_OPTIONS_PRIMITIVE: Array<EuiComboBoxOptionOption<RuntimeType>> = [ { label: 'Keyword', value: 'keyword', @@ -39,3 +39,11 @@ export const RUNTIME_FIELD_OPTIONS: Array<EuiComboBoxOptionOption<RuntimeType>> value: 'geo_point', }, ]; + +export const RUNTIME_FIELD_OPTIONS = [ + ...RUNTIME_FIELD_OPTIONS_PRIMITIVE, + { + label: 'Composite', + value: 'composite', + } as EuiComboBoxOptionOption<RuntimeType>, +]; diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/field_detail.tsx b/src/plugins/data_view_field_editor/public/components/field_editor/field_detail.tsx new file mode 100644 index 00000000000000..b9db87b65e3cdc --- /dev/null +++ b/src/plugins/data_view_field_editor/public/components/field_editor/field_detail.tsx @@ -0,0 +1,117 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiCode } from '@elastic/eui'; +import { AdvancedParametersSection } from './advanced_parameters_section'; +import { FormRow } from './form_row'; +import { PopularityField, FormatField, ScriptField, CustomLabelField } from './form_fields'; +import { useFieldEditorContext } from '../field_editor_context'; + +const geti18nTexts = (): { + [key: string]: { title: string; description: JSX.Element | string }; +} => ({ + customLabel: { + title: i18n.translate('indexPatternFieldEditor.editor.form.customLabelTitle', { + defaultMessage: 'Set custom label', + }), + description: i18n.translate('indexPatternFieldEditor.editor.form.customLabelDescription', { + defaultMessage: `Create a label to display in place of the field name in Discover, Maps, and Visualize. Useful for shortening a long field name. Queries and filters use the original field name.`, + }), + }, + value: { + title: i18n.translate('indexPatternFieldEditor.editor.form.valueTitle', { + defaultMessage: 'Set value', + }), + description: ( + <FormattedMessage + id="indexPatternFieldEditor.editor.form.valueDescription" + defaultMessage="Set a value for the field instead of retrieving it from the field with the same name in {source}." + values={{ + source: <EuiCode>{'_source'}</EuiCode>, + }} + /> + ), + }, + + format: { + title: i18n.translate('indexPatternFieldEditor.editor.form.formatTitle', { + defaultMessage: 'Set format', + }), + description: i18n.translate('indexPatternFieldEditor.editor.form.formatDescription', { + defaultMessage: `Set your preferred format for displaying the value. Changing the format can affect the value and prevent highlighting in Discover.`, + }), + }, + + popularity: { + title: i18n.translate('indexPatternFieldEditor.editor.form.popularityTitle', { + defaultMessage: 'Set popularity', + }), + description: i18n.translate('indexPatternFieldEditor.editor.form.popularityDescription', { + defaultMessage: `Adjust the popularity to make the field appear higher or lower in the fields list. By default, Discover orders fields from most selected to least selected.`, + }), + }, +}); + +export const FieldDetail = ({}) => { + const { links, existingConcreteFields, fieldTypeToProcess } = useFieldEditorContext(); + const i18nTexts = geti18nTexts(); + return ( + <> + {/* Set custom label */} + <FormRow + title={i18nTexts.customLabel.title} + description={i18nTexts.customLabel.description} + formFieldPath="__meta__.isCustomLabelVisible" + data-test-subj="customLabelRow" + withDividerRule + > + <CustomLabelField /> + </FormRow> + + {/* Set value */} + {fieldTypeToProcess === 'runtime' && ( + <FormRow + title={i18nTexts.value.title} + description={i18nTexts.value.description} + formFieldPath="__meta__.isValueVisible" + data-test-subj="valueRow" + withDividerRule + > + <ScriptField existingConcreteFields={existingConcreteFields} links={links} /> + </FormRow> + )} + + {/* Set custom format */} + <FormRow + title={i18nTexts.format.title} + description={i18nTexts.format.description} + formFieldPath="__meta__.isFormatVisible" + data-test-subj="formatRow" + withDividerRule + > + <FormatField /> + </FormRow> + + {/* Advanced settings */} + <AdvancedParametersSection> + <FormRow + title={i18nTexts.popularity.title} + description={i18nTexts.popularity.description} + formFieldPath="__meta__.isPopularityVisible" + data-test-subj="popularityRow" + withDividerRule + > + <PopularityField /> + </FormRow> + </AdvancedParametersSection> + </> + ); +}; diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/field_editor.tsx b/src/plugins/data_view_field_editor/public/components/field_editor/field_editor.tsx index 47b871196be038..88c91ab6457767 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor/field_editor.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_editor/field_editor.tsx @@ -6,18 +6,10 @@ * Side Public License, v 1. */ -import React, { useEffect } from 'react'; +import React, { useEffect, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; import { get } from 'lodash'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiComboBoxOptionOption, - EuiCode, - EuiCallOut, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiCallOut } from '@elastic/eui'; import { Form, @@ -28,6 +20,7 @@ import { UseField, TextField, RuntimeType, + RuntimePrimitiveTypes, } from '../../shared_imports'; import { Field } from '../../types'; import { useFieldEditorContext } from '../field_editor_context'; @@ -35,16 +28,12 @@ import { useFieldPreviewContext } from '../preview'; import { RUNTIME_FIELD_OPTIONS } from './constants'; import { schema } from './form_schema'; -import { getNameFieldConfig } from './lib'; -import { - TypeField, - CustomLabelField, - ScriptField, - FormatField, - PopularityField, -} from './form_fields'; -import { FormRow } from './form_row'; -import { AdvancedParametersSection } from './advanced_parameters_section'; +import { getNameFieldConfig, getFieldPreviewChanges } from './lib'; +import { TypeField } from './form_fields'; +import { FieldDetail } from './field_detail'; +import { CompositeEditor } from './composite_editor'; +import { TypeSelection } from './types'; +import { ChangeType } from '../preview/types'; export interface FieldEditorFormState { isValid: boolean | undefined; @@ -53,8 +42,9 @@ export interface FieldEditorFormState { submit: FormHook<Field>['submit']; } -export interface FieldFormInternal extends Omit<Field, 'type' | 'internalType'> { - type: Array<EuiComboBoxOptionOption<RuntimeType>>; +export interface FieldFormInternal extends Omit<Field, 'type' | 'internalType' | 'fields'> { + fields?: Record<string, { type: RuntimePrimitiveTypes }>; + type: TypeSelection; __meta__: { isCustomLabelVisible: boolean; isValueVisible: boolean; @@ -72,66 +62,28 @@ export interface Props { onFormModifiedChange?: (isModified: boolean) => void; } -const geti18nTexts = (): { - [key: string]: { title: string; description: JSX.Element | string }; -} => ({ - customLabel: { - title: i18n.translate('indexPatternFieldEditor.editor.form.customLabelTitle', { - defaultMessage: 'Set custom label', - }), - description: i18n.translate('indexPatternFieldEditor.editor.form.customLabelDescription', { - defaultMessage: `Create a label to display in place of the field name in Discover, Maps, and Visualize. Useful for shortening a long field name. Queries and filters use the original field name.`, - }), - }, - value: { - title: i18n.translate('indexPatternFieldEditor.editor.form.valueTitle', { - defaultMessage: 'Set value', - }), - description: ( - <FormattedMessage - id="indexPatternFieldEditor.editor.form.valueDescription" - defaultMessage="Set a value for the field instead of retrieving it from the field with the same name in {source}." - values={{ - source: <EuiCode>{'_source'}</EuiCode>, - }} - /> - ), - }, - format: { - title: i18n.translate('indexPatternFieldEditor.editor.form.formatTitle', { - defaultMessage: 'Set format', - }), - description: i18n.translate('indexPatternFieldEditor.editor.form.formatDescription', { - defaultMessage: `Set your preferred format for displaying the value. Changing the format can affect the value and prevent highlighting in Discover.`, - }), - }, - popularity: { - title: i18n.translate('indexPatternFieldEditor.editor.form.popularityTitle', { - defaultMessage: 'Set popularity', - }), - description: i18n.translate('indexPatternFieldEditor.editor.form.popularityDescription', { - defaultMessage: `Adjust the popularity to make the field appear higher or lower in the fields list. By default, Discover orders fields from most selected to least selected.`, - }), - }, -}); - const changeWarning = i18n.translate('indexPatternFieldEditor.editor.form.changeWarning', { defaultMessage: 'Changing name or type can break searches and visualizations that rely on this field.', }); -const formDeserializer = (field: Field): FieldFormInternal => { - let fieldType: Array<EuiComboBoxOptionOption<RuntimeType>>; - if (!field.type) { - fieldType = [RUNTIME_FIELD_OPTIONS[0]]; - } else { - const label = RUNTIME_FIELD_OPTIONS.find(({ value }) => value === field.type)?.label; - fieldType = [{ label: label ?? field.type, value: field.type as RuntimeType }]; +const fieldTypeToComboBoxOption = (type: Field['type']): TypeSelection => { + if (type) { + const label = RUNTIME_FIELD_OPTIONS.find(({ value }) => value === type)?.label; + return [{ label: label ?? type, value: type as RuntimeType }]; } + return [RUNTIME_FIELD_OPTIONS[0]]; +}; + +const formDeserializer = (field: Field): FieldFormInternal => { + const fieldType = fieldTypeToComboBoxOption(field.type); + + const format = field.format === null ? undefined : field.format; return { ...field, type: fieldType, + format, __meta__: { isCustomLabelVisible: field.customLabel !== undefined, isValueVisible: field.script !== undefined, @@ -142,18 +94,21 @@ const formDeserializer = (field: Field): FieldFormInternal => { }; const formSerializer = (field: FieldFormInternal): Field => { - const { __meta__, type, ...rest } = field; + const { __meta__, type, format, ...rest } = field; return { - type: type[0].value!, + type: type && type[0].value!, + // By passing "null" we are explicitly telling DataView to remove the + // format if there is one defined for the field. + format: format === undefined ? null : format, ...rest, }; }; const FieldEditorComponent = ({ field, onChange, onFormModifiedChange }: Props) => { - const { links, namesNotAllowed, existingConcreteFields, fieldTypeToProcess } = - useFieldEditorContext(); + const { namesNotAllowed, fieldTypeToProcess, fieldName$, subfields$ } = useFieldEditorContext(); const { params: { update: updatePreviewParams }, + fieldPreview$, } = useFieldPreviewContext(); const { form } = useForm<Field, FieldFormInternal>({ defaultValue: field, @@ -161,10 +116,10 @@ const FieldEditorComponent = ({ field, onChange, onFormModifiedChange }: Props) deserializer: formDeserializer, serializer: formSerializer, }); + const { submit, isValid: isFormValid, isSubmitted, getFields, isSubmitting } = form; const nameFieldConfig = getNameFieldConfig(namesNotAllowed, field); - const i18nTexts = geti18nTexts(); const [formData] = useFormData<FieldFormInternal>({ form }); const isFormModified = useFormIsModified({ @@ -177,6 +132,19 @@ const FieldEditorComponent = ({ field, onChange, onFormModifiedChange }: Props) ], }); + // use observable to sidestep react state + useEffect(() => { + const sub = form.subscribe(({ data }) => { + if (data.internal.name !== fieldName$.getValue()) { + fieldName$.next(data.internal.name); + } + }); + + return () => { + sub.unsubscribe(); + }; + }, [form, fieldName$]); + const { name: updatedName, type: updatedType, @@ -189,6 +157,50 @@ const FieldEditorComponent = ({ field, onChange, onFormModifiedChange }: Props) const isValueVisible = get(formData, '__meta__.isValueVisible'); + const resetTypes = useCallback(() => { + const lastVal = fieldPreview$.getValue(); + // resets the preview history to an empty set + fieldPreview$.next([]); + // apply the last preview to get all the types + fieldPreview$.next(lastVal); + }, [fieldPreview$]); + + useEffect(() => { + const existingCompositeField = !!Object.keys(subfields$.getValue() || {}).length; + + const changes$ = getFieldPreviewChanges(fieldPreview$); + + const subChanges = changes$.subscribe((previewFields) => { + const fields = subfields$.getValue(); + + const modifiedFields = { ...fields }; + + Object.entries(previewFields).forEach(([name, change]) => { + if (change.changeType === ChangeType.DELETE) { + delete modifiedFields[name]; + } + if (change.changeType === ChangeType.UPSERT) { + modifiedFields[name] = { type: change.type! }; + } + }); + + subfields$.next(modifiedFields); + // necessary to maintain script code when changing types + form.updateFieldValues({ ...form.getFormData() }); + }); + + // first preview value is skipped for saved fields, need to populate for new fields and rerenders + if (!existingCompositeField) { + fieldPreview$.next([]); + } else if (fieldPreview$.getValue()) { + fieldPreview$.next(fieldPreview$.getValue()); + } + + return () => { + subChanges.unsubscribe(); + }; + }, [form, fieldPreview$, subfields$]); + useEffect(() => { if (onChange) { onChange({ isValid: isFormValid, isSubmitted, isSubmitting, submit }); @@ -202,16 +214,25 @@ const FieldEditorComponent = ({ field, onChange, onFormModifiedChange }: Props) script: isValueVisible === false || Boolean(updatedScript?.source.trim()) === false ? null - : updatedScript, + : { source: updatedScript!.source }, format: updatedFormat?.id !== undefined ? updatedFormat : null, + parentName: field?.parentName, }); - }, [updatedName, updatedType, updatedScript, isValueVisible, updatedFormat, updatePreviewParams]); + }, [ + updatedName, + updatedType, + updatedScript, + isValueVisible, + updatedFormat, + updatePreviewParams, + field, + ]); useEffect(() => { if (onFormModifiedChange) { onFormModifiedChange(isFormModified); } - }, [isFormModified, onFormModifiedChange]); + }, [isFormModified, onFormModifiedChange, form]); return ( <Form @@ -242,10 +263,13 @@ const FieldEditorComponent = ({ field, onChange, onFormModifiedChange }: Props) {/* Type */} <EuiFlexItem> - <TypeField isDisabled={fieldTypeToProcess === 'concrete'} /> + <TypeField + isDisabled={fieldTypeToProcess === 'concrete'} + includeComposite={true} + path="type" + /> </EuiFlexItem> </EuiFlexGroup> - {(nameHasChanged || typeHasChanged) && ( <> <EuiSpacer size="xs" /> @@ -259,56 +283,25 @@ const FieldEditorComponent = ({ field, onChange, onFormModifiedChange }: Props) </> )} <EuiSpacer size="xl" /> - - {/* Set custom label */} - <FormRow - title={i18nTexts.customLabel.title} - description={i18nTexts.customLabel.description} - formFieldPath="__meta__.isCustomLabelVisible" - data-test-subj="customLabelRow" - withDividerRule - > - <CustomLabelField /> - </FormRow> - - {/* Set value */} - {fieldTypeToProcess === 'runtime' && ( - <FormRow - title={i18nTexts.value.title} - description={i18nTexts.value.description} - formFieldPath="__meta__.isValueVisible" - data-test-subj="valueRow" - withDividerRule - > - <ScriptField existingConcreteFields={existingConcreteFields} links={links} /> - </FormRow> + {field?.parentName && ( + <> + <EuiCallOut + iconType="iInCircle" + title={i18n.translate('indexPatternFieldEditor.editor.form.subFieldParentInfo', { + defaultMessage: "Field value is defined by '{parentName}'", + values: { parentName: field?.parentName }, + })} + /> + <EuiSpacer size="xl" /> + </> + )} + {updatedType && updatedType[0].value !== 'composite' ? ( + <FieldDetail /> + ) : ( + <CompositeEditor onReset={resetTypes} /> )} - - {/* Set custom format */} - <FormRow - title={i18nTexts.format.title} - description={i18nTexts.format.description} - formFieldPath="__meta__.isFormatVisible" - data-test-subj="formatRow" - withDividerRule - > - <FormatField /> - </FormRow> - - {/* Advanced settings */} - <AdvancedParametersSection> - <FormRow - title={i18nTexts.popularity.title} - description={i18nTexts.popularity.description} - formFieldPath="__meta__.isPopularityVisible" - data-test-subj="popularityRow" - withDividerRule - > - <PopularityField /> - </FormRow> - </AdvancedParametersSection> </Form> ); }; -export const FieldEditor = React.memo(FieldEditorComponent) as typeof FieldEditorComponent; +export const FieldEditor = FieldEditorComponent as typeof FieldEditorComponent; diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/format_field.tsx b/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/format_field.tsx index d90d7ef6cdf687..9518ba6cc89ed2 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/format_field.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/format_field.tsx @@ -7,9 +7,14 @@ */ import { EuiCallOut, EuiSpacer } from '@elastic/eui'; -import { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; import React, { useEffect, useRef, useState } from 'react'; -import { ES_FIELD_TYPES, UseField, useFormContext, useFormData } from '../../../shared_imports'; +import { + UseField, + useFormData, + ES_FIELD_TYPES, + useFormContext, + SerializedFieldFormat, +} from '../../../shared_imports'; import { useFieldEditorContext } from '../../field_editor_context'; import { FormatSelectEditor } from '../../field_format_editor'; import type { FieldFormInternal } from '../field_editor'; diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/script_field.tsx b/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/script_field.tsx index a7cd508401c6cc..dd66369a37d3f9 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/script_field.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/script_field.tsx @@ -31,6 +31,7 @@ import type { FieldFormInternal } from '../field_editor'; interface Props { links: { runtimePainless: string }; existingConcreteFields?: Array<{ name: string; type: string }>; + placeholder?: string; } const mapReturnTypeToPainlessContext = (runtimeType: RuntimeType): PainlessContext => { @@ -52,7 +53,7 @@ const mapReturnTypeToPainlessContext = (runtimeType: RuntimeType): PainlessConte } }; -const ScriptFieldComponent = ({ existingConcreteFields, links }: Props) => { +const ScriptFieldComponent = ({ existingConcreteFields, links, placeholder }: Props) => { const monacoEditor = useRef<monaco.editor.IStandaloneCodeEditor | null>(null); const editorValidationSubscription = useRef<Subscription>(); const fieldCurrentValue = useRef<string>(''); @@ -221,6 +222,7 @@ const ScriptFieldComponent = ({ existingConcreteFields, links }: Props) => { id="runtimeFieldScript" error={errorMessage} isInvalid={!isValid} + data-test-subj="scriptFieldRow" helpText={ <FormattedMessage id="indexPatternFieldEditor.editor.form.source.scriptFieldHelpText" @@ -276,6 +278,7 @@ const ScriptFieldComponent = ({ existingConcreteFields, links }: Props) => { defaultMessage: 'Script editor', } )} + placeholder={placeholder} /> </EuiFormRow> </> diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/type_field.tsx b/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/type_field.tsx index 36428579a30e86..d4eb463e670518 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/type_field.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_editor/form_fields/type_field.tsx @@ -9,18 +9,27 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiFormRow, EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; +import { EuiFormRow, EuiComboBox } from '@elastic/eui'; -import { UseField, RuntimeType } from '../../../shared_imports'; -import { RUNTIME_FIELD_OPTIONS } from '../constants'; +import { UseField } from '../../../shared_imports'; +import { RUNTIME_FIELD_OPTIONS, RUNTIME_FIELD_OPTIONS_PRIMITIVE } from '../constants'; +import { TypeSelection } from '../types'; interface Props { isDisabled?: boolean; + includeComposite?: boolean; + path: string; + defaultValue?: TypeSelection; } -export const TypeField = ({ isDisabled = false }: Props) => { +export const TypeField = ({ + isDisabled = false, + includeComposite, + path, + defaultValue = [RUNTIME_FIELD_OPTIONS_PRIMITIVE[0]], +}: Props) => { return ( - <UseField<Array<EuiComboBoxOptionOption<RuntimeType>>> path="type"> + <UseField<TypeSelection> path={path}> {({ label, value, setValue }) => { if (value === undefined) { return null; @@ -36,8 +45,8 @@ export const TypeField = ({ isDisabled = false }: Props) => { } )} singleSelection={{ asPlainText: true }} - options={RUNTIME_FIELD_OPTIONS} - selectedOptions={value} + options={includeComposite ? RUNTIME_FIELD_OPTIONS : RUNTIME_FIELD_OPTIONS_PRIMITIVE} + selectedOptions={value || defaultValue} onChange={(newValue) => { if (newValue.length === 0) { // Don't allow clearing the type. One must always be selected diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/form_schema.ts b/src/plugins/data_view_field_editor/public/components/field_editor/form_schema.ts index 8d49702b481544..391f54581f2588 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor/form_schema.ts +++ b/src/plugins/data_view_field_editor/public/components/field_editor/form_schema.ts @@ -139,6 +139,9 @@ export const schema = { }, ], }, + fields: { + defaultValue: {}, + }, __meta__: { isCustomLabelVisible: { defaultValue: false, diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/lib.test.ts b/src/plugins/data_view_field_editor/public/components/field_editor/lib.test.ts new file mode 100644 index 00000000000000..d8a836ea583a30 --- /dev/null +++ b/src/plugins/data_view_field_editor/public/components/field_editor/lib.test.ts @@ -0,0 +1,67 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getFieldPreviewChanges } from './lib'; +import { BehaviorSubject } from 'rxjs'; +import { ChangeType, FieldPreview } from '../preview/types'; + +describe('getFieldPreviewChanges', () => { + it('should return new keys', (done) => { + const subj = new BehaviorSubject<FieldPreview[] | undefined>(undefined); + const changes = getFieldPreviewChanges(subj); + changes.subscribe((change) => { + expect(change).toStrictEqual({ hello: { changeType: ChangeType.UPSERT, type: 'keyword' } }); + done(); + }); + subj.next([]); + subj.next([{ key: 'hello', value: 'world', type: 'keyword' }]); + }); + + it('should return updated type', (done) => { + const subj = new BehaviorSubject<FieldPreview[] | undefined>(undefined); + const changes = getFieldPreviewChanges(subj); + changes.subscribe((change) => { + expect(change).toStrictEqual({ hello: { changeType: ChangeType.UPSERT, type: 'long' } }); + done(); + }); + subj.next([{ key: 'hello', value: 'world', type: 'keyword' }]); + subj.next([{ key: 'hello', value: 1, type: 'long' }]); + }); + + it('should remove keys', (done) => { + const subj = new BehaviorSubject<FieldPreview[] | undefined>(undefined); + const changes = getFieldPreviewChanges(subj); + changes.subscribe((change) => { + expect(change).toStrictEqual({ hello: { changeType: ChangeType.DELETE } }); + done(); + }); + subj.next([{ key: 'hello', value: 'world', type: 'keyword' }]); + subj.next([]); + }); + + it('should add, update, and remove keys in a single change', (done) => { + const subj = new BehaviorSubject<FieldPreview[] | undefined>(undefined); + const changes = getFieldPreviewChanges(subj); + changes.subscribe((change) => { + expect(change).toStrictEqual({ + hello: { changeType: ChangeType.UPSERT, type: 'long' }, + hello2: { changeType: ChangeType.DELETE }, + hello3: { changeType: ChangeType.UPSERT, type: 'keyword' }, + }); + done(); + }); + subj.next([ + { key: 'hello', value: 'world', type: 'keyword' }, + { key: 'hello2', value: 'world', type: 'keyword' }, + ]); + subj.next([ + { key: 'hello', value: 1, type: 'long' }, + { key: 'hello3', value: 'world', type: 'keyword' }, + ]); + }); +}); diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/lib.ts b/src/plugins/data_view_field_editor/public/components/field_editor/lib.ts index 5b2e66c66fe390..bad85541007909 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor/lib.ts +++ b/src/plugins/data_view_field_editor/public/components/field_editor/lib.ts @@ -7,16 +7,30 @@ */ import { i18n } from '@kbn/i18n'; +import { map, bufferCount, filter, BehaviorSubject } from 'rxjs'; +import { differenceWith, isEqual } from 'lodash'; import { ValidationFunc, FieldConfig } from '../../shared_imports'; -import { Field } from '../../types'; +import type { Field } from '../../types'; +import type { Context } from '../field_editor_context'; import { schema } from './form_schema'; import type { Props } from './field_editor'; +import { RUNTIME_FIELD_OPTIONS_PRIMITIVE } from './constants'; +import { ChangeType, FieldPreview } from '../preview/types'; + +import { RuntimePrimitiveTypes } from '../../shared_imports'; + +export interface Change { + changeType: ChangeType; + type?: RuntimePrimitiveTypes; +} + +export type ChangeSet = Record<string, Change>; const createNameNotAllowedValidator = - (namesNotAllowed: string[]): ValidationFunc<{}, string, string> => + (namesNotAllowed: Context['namesNotAllowed']): ValidationFunc<{}, string, string> => ({ value }) => { - if (namesNotAllowed.includes(value)) { + if (namesNotAllowed.fields.includes(value)) { return { message: i18n.translate( 'indexPatternFieldEditor.editor.runtimeFieldsEditor.existRuntimeFieldNamesValidationErrorMessage', @@ -25,6 +39,15 @@ const createNameNotAllowedValidator = } ), }; + } else if (namesNotAllowed.runtimeComposites.includes(value)) { + return { + message: i18n.translate( + 'indexPatternFieldEditor.editor.runtimeFieldsEditor.existCompositeNamesValidationErrorMessage', + { + defaultMessage: 'A runtime composite with this name already exists.', + } + ), + }; } }; @@ -36,7 +59,7 @@ const createNameNotAllowedValidator = * @param field Initial value of the form */ export const getNameFieldConfig = ( - namesNotAllowed?: string[], + namesNotAllowed?: Context['namesNotAllowed'], field?: Props['field'] ): FieldConfig<string, Field> => { const nameFieldConfig = schema.name as FieldConfig<string, Field>; @@ -45,16 +68,53 @@ export const getNameFieldConfig = ( return nameFieldConfig; } + const filterOutCurrentFieldName = (name: string) => name !== field?.name; + // Add validation to not allow duplicates return { ...nameFieldConfig!, validations: [ ...(nameFieldConfig.validations ?? []), { - validator: createNameNotAllowedValidator( - namesNotAllowed.filter((name) => name !== field?.name) - ), + validator: createNameNotAllowedValidator({ + fields: namesNotAllowed.fields.filter(filterOutCurrentFieldName), + runtimeComposites: namesNotAllowed.runtimeComposites.filter(filterOutCurrentFieldName), + }), }, ], }; }; + +export const valueToComboBoxOption = (value: string) => + RUNTIME_FIELD_OPTIONS_PRIMITIVE.find(({ value: optionValue }) => optionValue === value); + +export const getFieldPreviewChanges = (subject: BehaviorSubject<FieldPreview[] | undefined>) => + subject.pipe( + filter((preview) => preview !== undefined), + map((items) => + // reduce the fields to make diffing easier + items!.map((item) => { + const key = item.key.slice(item.key.search('\\.') + 1); + return { name: key, type: item.type! }; + }) + ), + bufferCount(2, 1), + // convert values into diff descriptions + map(([prev, next]) => { + const changes = differenceWith(next, prev, isEqual).reduce<ChangeSet>((col, item) => { + col[item.name] = { + changeType: ChangeType.UPSERT, + type: item.type as RuntimePrimitiveTypes, + }; + return col; + }, {} as ChangeSet); + + prev.forEach((prevItem) => { + if (!next.find((nextItem) => nextItem.name === prevItem.name)) { + changes[prevItem.name] = { changeType: ChangeType.DELETE }; + } + }); + return changes; + }), + filter((fields) => Object.keys(fields).length > 0) + ); diff --git a/src/plugins/data_view_field_editor/public/components/field_editor/types.ts b/src/plugins/data_view_field_editor/public/components/field_editor/types.ts new file mode 100644 index 00000000000000..3c8aba9149ea14 --- /dev/null +++ b/src/plugins/data_view_field_editor/public/components/field_editor/types.ts @@ -0,0 +1,18 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { EuiComboBoxOptionOption } from '@elastic/eui'; + +import { RuntimeType } from '../../shared_imports'; + +export type TypeSelection = Array<EuiComboBoxOptionOption<RuntimeType>>; + +export interface FieldTypeInfo { + name: string; + type: string; +} diff --git a/src/plugins/data_view_field_editor/public/components/field_editor_context.tsx b/src/plugins/data_view_field_editor/public/components/field_editor_context.tsx index 6cadc094bb35ff..494d6034f66690 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor_context.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_editor_context.tsx @@ -8,8 +8,13 @@ import React, { createContext, useContext, FunctionComponent, useMemo } from 'react'; import { NotificationsStart, CoreStart } from '@kbn/core/public'; -import { FieldFormatsStart } from '../shared_imports'; -import type { DataView, DataPublicPluginStart } from '../shared_imports'; +import type { BehaviorSubject } from 'rxjs'; +import type { + DataView, + DataPublicPluginStart, + FieldFormatsStart, + RuntimeFieldSubFields, +} from '../shared_imports'; import { ApiService } from '../lib/api'; import type { InternalFieldType, PluginStart } from '../types'; @@ -32,7 +37,10 @@ export interface Context { * e.g we probably don't want a user to give a name of an existing * runtime field (for that the user should edit the existing runtime field). */ - namesNotAllowed: string[]; + namesNotAllowed: { + fields: string[]; + runtimeComposites: string[]; + }; /** * An array of existing concrete fields. If the user gives a name to the runtime * field that matches one of the concrete fields, a callout will be displayed @@ -40,6 +48,8 @@ export interface Context { * It is also used to provide the list of field autocomplete suggestions to the code editor. */ existingConcreteFields: Array<{ name: string; type: string }>; + fieldName$: BehaviorSubject<string>; + subfields$: BehaviorSubject<RuntimeFieldSubFields | undefined>; } const fieldEditorContext = createContext<Context | undefined>(undefined); @@ -55,6 +65,8 @@ export const FieldEditorProvider: FunctionComponent<Context> = ({ namesNotAllowed, existingConcreteFields, children, + fieldName$, + subfields$, }) => { const ctx = useMemo<Context>( () => ({ @@ -67,6 +79,8 @@ export const FieldEditorProvider: FunctionComponent<Context> = ({ fieldFormatEditors, namesNotAllowed, existingConcreteFields, + fieldName$, + subfields$, }), [ dataView, @@ -78,6 +92,8 @@ export const FieldEditorProvider: FunctionComponent<Context> = ({ fieldFormatEditors, namesNotAllowed, existingConcreteFields, + fieldName$, + subfields$, ] ); diff --git a/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content.tsx b/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content.tsx index 9968838919513a..edd0a7bc70b627 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content.tsx @@ -20,6 +20,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { euiFlyoutClassname } from '../constants'; import type { Field } from '../types'; import { ModifiedFieldModal, SaveFieldTypeOrNameChangedModal } from './confirm_modals'; + import { FieldEditor, FieldEditorFormState } from './field_editor/field_editor'; import { useFieldEditorContext } from './field_editor_context'; import { FlyoutPanels } from './flyout_panels'; @@ -69,7 +70,8 @@ const FieldEditorFlyoutContentComponent = ({ }: Props) => { const isMounted = useRef(false); const isEditingExistingField = !!fieldToEdit; - const { dataView } = useFieldEditorContext(); + const { dataView, subfields$ } = useFieldEditorContext(); + const { panel: { isVisible: isPanelVisible }, } = useFieldPreviewContext(); @@ -100,7 +102,7 @@ const FieldEditorFlyoutContentComponent = ({ }, [isFormModified]); const onClickSave = useCallback(async () => { - const { isValid, data } = await submit(); + const { isValid, data: updatedField } = await submit(); if (!isMounted.current) { // User has closed the flyout meanwhile submitting the form @@ -108,8 +110,8 @@ const FieldEditorFlyoutContentComponent = ({ } if (isValid) { - const nameChange = fieldToEdit?.name !== data.name; - const typeChange = fieldToEdit?.type !== data.type; + const nameChange = fieldToEdit?.name !== updatedField.name; + const typeChange = fieldToEdit?.type !== updatedField.type; if (isEditingExistingField && (nameChange || typeChange)) { setModalVisibility({ @@ -117,10 +119,14 @@ const FieldEditorFlyoutContentComponent = ({ confirmChangeNameOrType: true, }); } else { - onSave(data); + if (updatedField.type === 'composite') { + onSave({ ...updatedField, fields: subfields$.getValue() }); + } else { + onSave(updatedField); + } } } - }, [onSave, submit, fieldToEdit, isEditingExistingField]); + }, [onSave, submit, fieldToEdit, isEditingExistingField, subfields$]); const onClickCancel = useCallback(() => { const canClose = canCloseValidator(); @@ -136,8 +142,12 @@ const FieldEditorFlyoutContentComponent = ({ <SaveFieldTypeOrNameChangedModal fieldName={fieldToEdit?.name!} onConfirm={async () => { - const { data } = await submit(); - onSave(data); + const { data: updatedField } = await submit(); + if (updatedField.type === 'composite') { + onSave({ ...updatedField, fields: subfields$.getValue() }); + } else { + onSave(updatedField); + } }} onCancel={() => { setModalVisibility(defaultModalVisibility); diff --git a/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content_container.tsx b/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content_container.tsx index 6696cf1e48b553..34740187d77d9d 100644 --- a/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content_container.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_editor_flyout_content_container.tsx @@ -11,18 +11,19 @@ import { DocLinksStart, NotificationsStart, CoreStart } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { METRIC_TYPE } from '@kbn/analytics'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import { BehaviorSubject } from 'rxjs'; import { DataViewField, DataView, DataPublicPluginStart, - RuntimeType, UsageCollectionStart, DataViewsPublicPluginStart, + FieldFormatsStart, + RuntimeType, } from '../shared_imports'; import type { Field, PluginStart, InternalFieldType } from '../types'; import { pluginName } from '../constants'; -import { deserializeField, getLinks, ApiService } from '../lib'; +import { getLinks, ApiService } from '../lib'; import { FieldEditorFlyoutContent, Props as FieldEditorFlyoutContentProps, @@ -32,7 +33,7 @@ import { FieldPreviewProvider } from './preview'; export interface Props { /** Handler for the "save" footer button */ - onSave: (field: DataViewField) => void; + onSave: (field: DataViewField[]) => void; /** Handler for the "cancel" footer button */ onCancel: () => void; onMounted?: FieldEditorFlyoutContentProps['onMounted']; @@ -43,7 +44,7 @@ export interface Props { /** The Kibana field type of the field to create or edit (default: "runtime") */ fieldTypeToProcess: InternalFieldType; /** Optional field to edit */ - fieldToEdit?: DataViewField; + fieldToEdit?: Field; /** Optional initial configuration for new field */ fieldToCreate?: Field; /** Services */ @@ -87,7 +88,16 @@ export const FieldEditorFlyoutContentContainer = ({ const { fields } = dataView; - const namesNotAllowed = useMemo(() => fields.map((fld) => fld.name), [fields]); + const namesNotAllowed = useMemo(() => { + const fieldNames = dataView.fields.map((fld) => fld.name); + const runtimeCompositeNames = Object.entries(dataView.getAllRuntimeFields()) + .filter(([, _runtimeField]) => _runtimeField.type === 'composite') + .map(([_runtimeFieldName]) => _runtimeFieldName); + return { + fields: fieldNames, + runtimeComposites: runtimeCompositeNames, + }; + }, [dataView]); const existingConcreteFields = useMemo(() => { const existing: Array<{ name: string; type: string }> = []; @@ -116,9 +126,12 @@ export const FieldEditorFlyoutContentContainer = ({ [apiService, search, notifications] ); - const saveField = useCallback( - async (updatedField: Field) => { - setIsSaving(true); + const updateRuntimeField = useCallback( + (updatedField: Field): DataViewField[] => { + const nameHasChanged = Boolean(fieldToEdit) && fieldToEdit!.name !== updatedField.name; + const typeHasChanged = Boolean(fieldToEdit) && fieldToEdit!.type !== updatedField.type; + const hasChangeToOrFromComposite = + typeHasChanged && (fieldToEdit!.type === 'composite' || updatedField.type === 'composite'); const { script } = updatedField; @@ -128,13 +141,14 @@ export const FieldEditorFlyoutContentContainer = ({ // eslint-disable-next-line no-empty } catch {} // rename an existing runtime field - if (fieldToEdit?.name && fieldToEdit.name !== updatedField.name) { - dataView.removeRuntimeField(fieldToEdit.name); + if (nameHasChanged || hasChangeToOrFromComposite) { + dataView.removeRuntimeField(fieldToEdit!.name); } dataView.addRuntimeField(updatedField.name, { type: updatedField.type as RuntimeType, script, + fields: updatedField.fields, }); } else { try { @@ -143,22 +157,54 @@ export const FieldEditorFlyoutContentContainer = ({ } catch {} } + return dataView.addRuntimeField(updatedField.name, updatedField); + }, + [fieldToEdit, dataView, fieldTypeToProcess, usageCollection] + ); + + const updateConcreteField = useCallback( + (updatedField: Field): DataViewField[] => { const editedField = dataView.getFieldByName(updatedField.name); + if (!editedField) { + throw new Error( + `Unable to find field named '${updatedField.name}' on index pattern '${dataView.title}'` + ); + } + + // Update custom label, popularity and format + dataView.setFieldCustomLabel(updatedField.name, updatedField.customLabel); + + editedField.count = updatedField.popularity || 0; + if (updatedField.format) { + dataView.setFieldFormat(updatedField.name, updatedField.format!); + } else { + dataView.deleteFieldFormat(updatedField.name); + } + + return [editedField]; + }, + [dataView] + ); + + const saveField = useCallback( + async (updatedField: Field) => { try { - if (!editedField) { - throw new Error( - `Unable to find field named '${updatedField.name}' on index pattern '${dataView.title}'` - ); - } + usageCollection.reportUiCounter( + pluginName, + METRIC_TYPE.COUNT, + fieldTypeToProcess === 'runtime' ? 'save_runtime' : 'save_concrete' + ); + // eslint-disable-next-line no-empty + } catch {} - dataView.setFieldCustomLabel(updatedField.name, updatedField.customLabel); - editedField.count = updatedField.popularity || 0; - if (updatedField.format) { - dataView.setFieldFormat(updatedField.name, updatedField.format); - } else { - dataView.deleteFieldFormat(updatedField.name); - } + setIsSaving(true); + + try { + const editedFields: DataViewField[] = + fieldTypeToProcess === 'runtime' + ? updateRuntimeField(updatedField) + : updateConcreteField(updatedField as Field); const afterSave = () => { const message = i18n.translate('indexPatternFieldEditor.deleteField.savedHeader', { @@ -167,17 +213,15 @@ export const FieldEditorFlyoutContentContainer = ({ }); notifications.toasts.addSuccess(message); setIsSaving(false); - onSave(editedField); + onSave(editedFields); }; - if (!dataView.isPersisted()) { - afterSave(); - return; + if (dataView.isPersisted()) { + await dataViews.updateSavedObject(dataView); } + afterSave(); - await dataViews.updateSavedObject(dataView).then(() => { - afterSave(); - }); + setIsSaving(false); } catch (e) { const title = i18n.translate('indexPatternFieldEditor.save.errorTitle', { defaultMessage: 'Failed to save field changes', @@ -192,7 +236,8 @@ export const FieldEditorFlyoutContentContainer = ({ dataViews, notifications, fieldTypeToProcess, - fieldToEdit?.name, + updateConcreteField, + updateRuntimeField, usageCollection, ] ); @@ -208,6 +253,8 @@ export const FieldEditorFlyoutContentContainer = ({ fieldFormats={fieldFormats} namesNotAllowed={namesNotAllowed} existingConcreteFields={existingConcreteFields} + fieldName$={new BehaviorSubject(fieldToEdit?.name || '')} + subfields$={new BehaviorSubject(fieldToEdit?.fields)} > <FieldPreviewProvider> <FieldEditorFlyoutContent @@ -215,7 +262,7 @@ export const FieldEditorFlyoutContentContainer = ({ onCancel={onCancel} onMounted={onMounted} fieldToCreate={fieldToCreate} - fieldToEdit={deserializeField(dataView, fieldToEdit)} + fieldToEdit={fieldToEdit} isSavingField={isSaving} /> </FieldPreviewProvider> diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx b/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx index 4211047878cca9..7058b04b090531 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx @@ -23,7 +23,7 @@ export interface FormatEditorProps { onError: (error?: string) => void; } -interface FormatEditorState { +export interface FormatEditorState { EditorComponent: LazyExoticComponent<FieldFormatEditor> | null; fieldFormatId?: string; } diff --git a/src/plugins/data_view_field_editor/public/components/field_format_editor/index.ts b/src/plugins/data_view_field_editor/public/components/field_format_editor/index.ts index 0c23c8de616cfe..2ae6b3149dc5f6 100644 --- a/src/plugins/data_view_field_editor/public/components/field_format_editor/index.ts +++ b/src/plugins/data_view_field_editor/public/components/field_format_editor/index.ts @@ -8,4 +8,6 @@ export type { FormatSelectEditorProps } from './field_format_editor'; export { FormatSelectEditor } from './field_format_editor'; +export type { FormatEditorState } from './format_editor'; +export type { Sample } from './types'; export * from './editors'; diff --git a/src/plugins/data_view_field_editor/public/components/preview/field_preview.tsx b/src/plugins/data_view_field_editor/public/components/preview/field_preview.tsx index 05339e6473b6b9..f331e62bd70164 100644 --- a/src/plugins/data_view_field_editor/public/components/preview/field_preview.tsx +++ b/src/plugins/data_view_field_editor/public/components/preview/field_preview.tsx @@ -27,6 +27,7 @@ export const FieldPreview = () => { params: { value: { name, script, format }, }, + isLoadingPreview, fields, error, documents: { fetchDocError }, @@ -36,15 +37,15 @@ export const FieldPreview = () => { // To show the preview we at least need a name to be defined, the script or the format // and an first response from the _execute API - const isEmptyPromptVisible = - name === null && script === null && format === null - ? true - : // If we have some result from the _execute API call don't show the empty prompt - Boolean(error) || fields.length > 0 - ? false - : name === null && format === null - ? true - : false; + let isEmptyPromptVisible = false; + const noParamDefined = name === null && script === null && format === null; + const haveResultFromPreview = error !== null || fields.length > 0; + + if (noParamDefined) { + isEmptyPromptVisible = true; + } else if (!haveResultFromPreview && !isLoadingPreview && name === null && format === null) { + isEmptyPromptVisible = true; + } const doRenderListOfFields = fetchDocError === null; const showWarningPreviewNotAvailable = isPreviewAvailable === false && fetchDocError === null; @@ -58,13 +59,13 @@ export const FieldPreview = () => { return null; } - const [field] = fields; - return ( <ul> - <li data-test-subj="fieldPreviewItem"> - <PreviewListItem field={field} isFromScript hasScriptError={Boolean(error)} /> - </li> + {fields.map((field, i) => ( + <li key={i} data-test-subj="fieldPreviewItem"> + <PreviewListItem field={field} isFromScript hasScriptError={Boolean(error)} /> + </li> + ))} </ul> ); }; diff --git a/src/plugins/data_view_field_editor/public/components/preview/field_preview_context.tsx b/src/plugins/data_view_field_editor/public/components/preview/field_preview_context.tsx index 127badffc826d0..6d6c38f8dfc61d 100644 --- a/src/plugins/data_view_field_editor/public/components/preview/field_preview_context.tsx +++ b/src/plugins/data_view_field_editor/public/components/preview/field_preview_context.tsx @@ -21,6 +21,8 @@ import useDebounce from 'react-use/lib/useDebounce'; import { i18n } from '@kbn/i18n'; import { get } from 'lodash'; import { castEsToKbnFieldTypeName } from '@kbn/field-types'; +import { BehaviorSubject } from 'rxjs'; +import { RuntimePrimitiveTypes } from '../../shared_imports'; import { parseEsError } from '../../lib/runtime_field_validation'; import { useFieldEditorContext } from '../field_editor_context'; @@ -33,6 +35,7 @@ import type { EsDocument, ScriptErrorCodes, FetchDocError, + FieldPreview, } from './types'; const fieldPreviewContext = createContext<Context | undefined>(undefined); @@ -44,6 +47,7 @@ const defaultParams: Params = { document: null, type: null, format: null, + parentName: null, }; export const defaultValueFormatter = (value: unknown) => { @@ -51,6 +55,14 @@ export const defaultValueFormatter = (value: unknown) => { return renderToString(<>{content}</>); }; +export const valueTypeToSelectedType = (value: unknown): RuntimePrimitiveTypes => { + const valueType = typeof value; + if (valueType === 'string') return 'keyword'; + if (valueType === 'number') return 'double'; + if (valueType === 'boolean') return 'boolean'; + return 'keyword'; +}; + export const FieldPreviewProvider: FunctionComponent = ({ children }) => { const previewCount = useRef(0); @@ -75,13 +87,18 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { api: { getFieldPreview }, }, fieldFormats, + fieldName$, } = useFieldEditorContext(); + const fieldPreview$ = useRef(new BehaviorSubject<FieldPreview[] | undefined>(undefined)); + /** Response from the Painless _execute API */ const [previewResponse, setPreviewResponse] = useState<{ fields: Context['fields']; error: Context['error']; }>({ fields: [], error: null }); + const [initialPreviewComplete, setInitialPreviewComplete] = useState(false); + /** Possible error while fetching sample documents */ const [fetchDocError, setFetchDocError] = useState<FetchDocError | null>(null); /** The parameters required for the Painless _execute API */ @@ -126,7 +143,7 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { isPreviewAvailable = false; } - const { name, document, script, format, type } = params; + const { name, document, script, format, type, parentName } = params; const updateParams: Context['params']['update'] = useCallback((updated) => { setParams((prev) => ({ ...prev, ...updated })); @@ -314,12 +331,67 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { [dataView, search] ); + const updateSingleFieldPreview = useCallback( + (fieldName: string, values: unknown[]) => { + const [value] = values; + const formattedValue = valueFormatter(value); + + setPreviewResponse({ + fields: [{ key: fieldName, value, formattedValue }], + error: null, + }); + }, + [valueFormatter] + ); + + const updateCompositeFieldPreview = useCallback( + (compositeValues: Record<string, unknown[]>) => { + const updatedFieldsInScript: string[] = []; + // if we're displaying a composite subfield, filter results + const filterSubfield = parentName ? (field: FieldPreview) => field.key === name : () => true; + + const fields = Object.entries(compositeValues) + .map<FieldPreview>(([key, values]) => { + // The Painless _execute API returns the composite field values under a map. + // Each of the key is prefixed with "composite_field." (e.g. "composite_field.field1: ['value']") + const { 1: fieldName } = key.split('composite_field.'); + updatedFieldsInScript.push(fieldName); + + const [value] = values; + const formattedValue = valueFormatter(value); + + return { + key: parentName + ? `${parentName ?? ''}.${fieldName}` + : `${fieldName$.getValue() ?? ''}.${fieldName}`, + value, + formattedValue, + type: valueTypeToSelectedType(value), + }; + }) + .filter(filterSubfield) + // ...and sort alphabetically + .sort((a, b) => a.key.localeCompare(b.key)); + + fieldPreview$.current.next(fields); + setPreviewResponse({ + fields, + error: null, + }); + }, + [valueFormatter, parentName, name, fieldPreview$, fieldName$] + ); + const updatePreview = useCallback(async () => { - if (scriptEditorValidation.isValidating) { + // don't prevent rendering if we're working with a composite subfield (has parentName) + if (!parentName && scriptEditorValidation.isValidating) { return; } - if (!allParamsDefined || !hasSomeParamsChanged || scriptEditorValidation.isValid === false) { + if ( + !parentName && + (!allParamsDefined || !hasSomeParamsChanged || scriptEditorValidation.isValid === false) + ) { setIsLoadingPreview(false); return; } @@ -332,11 +404,13 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { const currentApiCall = ++previewCount.current; + const previewScript = (parentName && dataView.getRuntimeField(parentName)?.script) || script!; + const response = await getFieldPreview({ index: currentDocIndex, document: document!, - context: `${type!}_field` as PainlessExecuteContext, - script: script!, + context: (parentName ? 'composite_field' : `${type!}_field`) as PainlessExecuteContext, + script: previewScript, }); if (currentApiCall !== previewCount.current) { @@ -363,33 +437,41 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { if (error) { setPreviewResponse({ - fields: [{ key: name ?? '', value: '', formattedValue: defaultValueFormatter('') }], + fields: [ + { + key: name ?? '', + value: '', + formattedValue: defaultValueFormatter(''), + }, + ], error: { code: 'PAINLESS_SCRIPT_ERROR', error: parseEsError(error) }, }); } else { - const [value] = values; - const formattedValue = valueFormatter(value); - - setPreviewResponse({ - fields: [{ key: name!, value, formattedValue }], - error: null, - }); + if (!Array.isArray(values)) { + updateCompositeFieldPreview(values); + } else { + updateSingleFieldPreview(name!, values); + } } } + setInitialPreviewComplete(true); setIsLoadingPreview(false); }, [ name, type, script, + parentName, + dataView, document, currentDocId, getFieldPreview, notifications.toasts, - valueFormatter, allParamsDefined, scriptEditorValidation, hasSomeParamsChanged, + updateSingleFieldPreview, + updateCompositeFieldPreview, currentDocIndex, ]); @@ -428,8 +510,10 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { () => ({ fields: previewResponse.fields, error: previewResponse.error, + fieldPreview$: fieldPreview$.current, isPreviewAvailable, isLoadingPreview, + initialPreviewComplete, params: { value: params, update: updateParams, @@ -470,6 +554,7 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { }), [ previewResponse, + fieldPreview$, fetchDocError, params, isPreviewAvailable, @@ -489,6 +574,7 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { from, reset, pinnedFields, + initialPreviewComplete, ] ); @@ -539,20 +625,61 @@ export const FieldPreviewProvider: FunctionComponent = ({ children }) => { */ useEffect(() => { setPreviewResponse((prev) => { - const { - fields: { 0: field }, - } = prev; + const { fields } = prev; + + let updatedFields: Context['fields'] = fields.map((field) => { + let key = name ?? ''; + + if (type === 'composite') { + // restore initial key segement (the parent name), which was not returned + const { 1: fieldName } = field.key.split('.'); + key = `${name ?? ''}.${fieldName}`; + } + + return { + ...field, + key, + }; + }); + + // If the user has entered a name but not yet any script we will display + // the field in the preview with just the name + if (updatedFields.length === 0 && name !== null) { + updatedFields = [ + { key: name, value: undefined, formattedValue: undefined, type: undefined }, + ]; + } - const nextValue = - script === null && Boolean(document) - ? get(document, name ?? '') // When there is no script we read the value from _source - : field?.value; + return { + ...prev, + fields: updatedFields, + }; + }); + }, [name, type, parentName]); - const formattedValue = valueFormatter(nextValue); + /** + * Whenever the format changes we immediately update the preview + */ + useEffect(() => { + setPreviewResponse((prev) => { + const { fields } = prev; return { ...prev, - fields: [{ ...field, key: name ?? '', value: nextValue, formattedValue }], + fields: fields.map((field) => { + const nextValue = + script === null && Boolean(document) + ? get(document, name ?? '') // When there is no script we try to read the value from _source + : field?.value; + + const formattedValue = valueFormatter(nextValue); + + return { + ...field, + value: nextValue, + formattedValue, + }; + }), }; }); }, [name, script, document, valueFormatter]); diff --git a/src/plugins/data_view_field_editor/public/components/preview/types.ts b/src/plugins/data_view_field_editor/public/components/preview/types.ts index 761c1db2094daa..881d512159516c 100644 --- a/src/plugins/data_view_field_editor/public/components/preview/types.ts +++ b/src/plugins/data_view_field_editor/public/components/preview/types.ts @@ -6,9 +6,14 @@ * Side Public License, v 1. */ -import { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; import React from 'react'; -import type { RuntimeField, RuntimeType } from '../../shared_imports'; +import { BehaviorSubject } from 'rxjs'; +import type { + RuntimeType, + RuntimeField, + SerializedFieldFormat, + RuntimePrimitiveTypes, +} from '../../shared_imports'; import type { RuntimeFieldPainlessError } from '../../types'; export type From = 'cluster' | 'custom'; @@ -57,17 +62,39 @@ export interface Params { script: Required<RuntimeField>['script'] | null; format: SerializedFieldFormat | null; document: { [key: string]: unknown } | null; + // used for composite subfields + parentName: string | null; } export interface FieldPreview { key: string; value: unknown; formattedValue?: string; + type?: string; } +export interface FieldTypeInfo { + name: string; + type: string; +} + +export enum ChangeType { + UPSERT = 'upsert', + DELETE = 'delete', +} +export interface Change { + changeType: ChangeType; + type?: RuntimePrimitiveTypes; +} + +export type ChangeSet = Record<string, Change>; + export interface Context { fields: FieldPreview[]; + fieldPreview$: BehaviorSubject<FieldPreview[] | undefined>; error: PreviewError | null; + fieldTypeInfo?: FieldTypeInfo[]; + initialPreviewComplete: boolean; params: { value: Params; update: (updated: Partial<Params>) => void; diff --git a/src/plugins/data_view_field_editor/public/components/utils.ts b/src/plugins/data_view_field_editor/public/components/utils.ts new file mode 100644 index 00000000000000..0a7a8a3990cdc5 --- /dev/null +++ b/src/plugins/data_view_field_editor/public/components/utils.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { RuntimeFieldSubFields, RuntimePrimitiveTypes } from '../shared_imports'; + +export const fieldTypeMapToRuntimeSpecFormat = ( + subfields: Record<string, RuntimePrimitiveTypes> +): RuntimeFieldSubFields => + Object.entries(subfields).reduce<RuntimeFieldSubFields>((col, [name, type]) => { + col[name] = { type }; + return col; + }, {}); diff --git a/src/plugins/data_view_field_editor/public/index.ts b/src/plugins/data_view_field_editor/public/index.ts index 7f76210c2c6f04..95ec7e4dcfdc44 100644 --- a/src/plugins/data_view_field_editor/public/index.ts +++ b/src/plugins/data_view_field_editor/public/index.ts @@ -26,7 +26,14 @@ export type { PluginStart as IndexPatternFieldEditorStart, } from './types'; export { DefaultFormatEditor } from './components/field_format_editor/editors/default/default'; -export type { FieldFormatEditorFactory, FieldFormatEditor, FormatEditorProps } from './components'; +export type { + FieldFormatEditorFactory, + FieldFormatEditor, + DeleteFieldProviderProps, + FormatEditorProps, + FormatEditorState, + Sample, +} from './components'; export function plugin() { return new IndexPatternFieldEditorPlugin(); @@ -35,4 +42,4 @@ export function plugin() { // Expose types export type { FormatEditorServiceStart } from './service'; export type { OpenFieldEditorOptions } from './open_editor'; -export type { OpenFieldDeleteModalOptions } from './open_delete_modal'; +export type { OpenFieldDeleteModalOptions, DeleteCompositeSubfield } from './open_delete_modal'; diff --git a/src/plugins/data_view_field_editor/public/lib/serialization.ts b/src/plugins/data_view_field_editor/public/lib/serialization.ts index 82051eef176636..6cf43810892260 100644 --- a/src/plugins/data_view_field_editor/public/lib/serialization.ts +++ b/src/plugins/data_view_field_editor/public/lib/serialization.ts @@ -14,13 +14,17 @@ export const deserializeField = (dataView: DataView, field?: DataViewField): Fie return undefined; } + const primitiveType = field?.esTypes ? (field.esTypes[0] as RuntimeType) : ('keyword' as const); + const editType = field.runtimeField?.type === 'composite' ? 'composite' : primitiveType; + return { name: field.name, - type: field?.esTypes ? (field.esTypes[0] as RuntimeType) : ('keyword' as const), + type: editType, script: field.runtimeField ? field.runtimeField.script : undefined, customLabel: field.customLabel, popularity: field.count, format: dataView.getFormatterForFieldNoDefault(field.name)?.toJSON(), + fields: field.runtimeField?.fields, }; }; diff --git a/src/plugins/data_view_field_editor/public/open_delete_modal.tsx b/src/plugins/data_view_field_editor/public/open_delete_modal.tsx index 2703653138fe0f..b2c9bba61b98fc 100644 --- a/src/plugins/data_view_field_editor/public/open_delete_modal.tsx +++ b/src/plugins/data_view_field_editor/public/open_delete_modal.tsx @@ -21,11 +21,24 @@ import { CloseEditor } from './types'; import { DeleteFieldModal } from './components/confirm_modals/delete_field_modal'; import { removeFields } from './lib/remove_fields'; +/** + * Options for opening the field editor + */ export interface OpenFieldDeleteModalOptions { + /** + * Config for the delete modal + */ ctx: { dataView: DataView; }; + /** + * Callback fired when fields are deleted + * @param fieldNames - the names of the deleted fields + */ onDelete?: (fieldNames: string[]) => void; + /** + * Names of the fields to be deleted + */ fieldName: string | string[]; } @@ -35,13 +48,38 @@ interface Dependencies { usageCollection: UsageCollectionStart; } +/** + * Error throw when there's an attempt to directly delete a composite subfield + * @param fieldName - the name of the field to delete + */ +export class DeleteCompositeSubfield extends Error { + constructor(fieldName: string) { + super(`Field '${fieldName} cannot be deleted because it is a composite subfield.`); + } +} + export const getFieldDeleteModalOpener = ({ core, dataViews, usageCollection }: Dependencies) => (options: OpenFieldDeleteModalOptions): CloseEditor => { + if (typeof options.fieldName === 'string') { + const fieldToDelete = options.ctx.dataView.getFieldByName(options.fieldName); + // we can check for composite type since composite runtime field definitions themselves don't become fields + const doesBelongToCompositeField = fieldToDelete?.runtimeField?.type === 'composite'; + + if (doesBelongToCompositeField) { + throw new DeleteCompositeSubfield(options.fieldName); + } + } + const { overlays, notifications } = core; let overlayRef: OverlayRef | null = null; + /** + * Open the delete field modal + * @param Options for delete field modal + * @returns Function to close the delete field modal + */ const openDeleteModal = ({ onDelete, fieldName, diff --git a/src/plugins/data_view_field_editor/public/open_editor.tsx b/src/plugins/data_view_field_editor/public/open_editor.tsx index d938ae52642b71..6d3dbc6c3f4cd9 100644 --- a/src/plugins/data_view_field_editor/public/open_editor.tsx +++ b/src/plugins/data_view_field_editor/public/open_editor.tsx @@ -15,11 +15,11 @@ import type { ApiService } from './lib/api'; import type { DataPublicPluginStart, DataView, - DataViewField, + UsageCollectionStart, + RuntimeType, DataViewsPublicPluginStart, FieldFormatsStart, - RuntimeType, - UsageCollectionStart, + DataViewField, } from './shared_imports'; import { createKibanaReactContext, toMountPoint } from './shared_imports'; import type { CloseEditor, Field, InternalFieldType, PluginStart } from './types'; @@ -37,8 +37,9 @@ export interface OpenFieldEditorOptions { }; /** * action to take after field is saved + * @param field - the fields that were saved */ - onSave?: (field: DataViewField) => void; + onSave?: (field: DataViewField[]) => void; /** * field to edit, for existing field */ @@ -100,7 +101,7 @@ export const getFieldEditorOpener = } }; - const onSaveField = (updatedField: DataViewField) => { + const onSaveField = (updatedField: DataViewField[]) => { closeEditor(); if (onSave) { @@ -108,9 +109,27 @@ export const getFieldEditorOpener = } }; - const fieldToEdit = fieldNameToEdit ? dataView.getFieldByName(fieldNameToEdit) : undefined; + const getRuntimeField = (name: string) => { + const fld = dataView.getAllRuntimeFields()[name]; + return { + name, + runtimeField: fld, + isMapped: false, + esTypes: [], + type: undefined, + customLabel: undefined, + count: undefined, + spec: { + parentName: undefined, + }, + }; + }; + + const dataViewField = fieldNameToEdit + ? dataView.getFieldByName(fieldNameToEdit) || getRuntimeField(fieldNameToEdit) + : undefined; - if (fieldNameToEdit && !fieldToEdit) { + if (fieldNameToEdit && !dataViewField) { const err = i18n.translate('indexPatternFieldEditor.noSuchFieldName', { defaultMessage: "Field named '{fieldName}' not found on index pattern", values: { fieldName: fieldNameToEdit }, @@ -121,14 +140,42 @@ export const getFieldEditorOpener = const isNewRuntimeField = !fieldNameToEdit; const isExistingRuntimeField = - fieldToEdit && - fieldToEdit.runtimeField && - !fieldToEdit.isMapped && - // treat composite field instances as mapped fields for field editing purposes - fieldToEdit.runtimeField.type !== ('composite' as RuntimeType); + dataViewField && + dataViewField.runtimeField && + !dataViewField.isMapped && + // treat composite subfield instances as mapped fields for field editing purposes + (dataViewField.runtimeField.type !== ('composite' as RuntimeType) || !dataViewField.type); + const fieldTypeToProcess: InternalFieldType = isNewRuntimeField || isExistingRuntimeField ? 'runtime' : 'concrete'; + let field: Field | undefined; + if (dataViewField) { + if (isExistingRuntimeField && dataViewField.runtimeField!.type === 'composite') { + // Composite runtime subfield + const [compositeName] = fieldNameToEdit!.split('.'); + field = { + name: compositeName, + ...dataView.getRuntimeField(compositeName)!, + }; + } else if (isExistingRuntimeField) { + // Runtime field + field = { + name: fieldNameToEdit!, + ...dataView.getRuntimeField(fieldNameToEdit!)!, + }; + } else { + // Concrete field + field = { + name: fieldNameToEdit!, + type: (dataViewField?.esTypes ? dataViewField.esTypes[0] : 'keyword') as RuntimeType, + customLabel: dataViewField.customLabel, + popularity: dataViewField.count, + format: dataView.getFormatterForFieldNoDefault(fieldNameToEdit!)?.toJSON(), + parentName: dataViewField.spec.parentName, + }; + } + } overlayRef = overlays.openFlyout( toMountPoint( <KibanaReactContextProvider> @@ -137,7 +184,7 @@ export const getFieldEditorOpener = onCancel={closeEditor} onMounted={onMounted} docLinks={docLinks} - fieldToEdit={fieldToEdit} + fieldToEdit={field} fieldToCreate={fieldToCreate} fieldTypeToProcess={fieldTypeToProcess} dataView={dataView} diff --git a/src/plugins/data_view_field_editor/public/shared_imports.ts b/src/plugins/data_view_field_editor/public/shared_imports.ts index 6d7c6b4222d50d..ff6621d64cbd1c 100644 --- a/src/plugins/data_view_field_editor/public/shared_imports.ts +++ b/src/plugins/data_view_field_editor/public/shared_imports.ts @@ -17,7 +17,14 @@ export type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; export type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; -export type { RuntimeType, RuntimeField } from '@kbn/data-views-plugin/common'; +export type { + RuntimeType, + RuntimeField, + RuntimeFieldSpec, + RuntimeFieldSubField, + RuntimeFieldSubFields, + RuntimePrimitiveTypes, +} from '@kbn/data-views-plugin/common'; export { KBN_FIELD_TYPES, ES_FIELD_TYPES } from '@kbn/data-plugin/common'; export { @@ -26,7 +33,7 @@ export { CodeEditor, } from '@kbn/kibana-react-plugin/public'; -export { FieldFormat } from '@kbn/field-formats-plugin/common'; +export type { FieldFormat, SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; export type { FormSchema, @@ -44,6 +51,7 @@ export { Form, UseField, useBehaviorSubject, + UseArray, } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib'; export { fieldValidators } from '@kbn/es-ui-shared-plugin/static/forms/helpers'; diff --git a/src/plugins/data_view_field_editor/public/types.ts b/src/plugins/data_view_field_editor/public/types.ts index 8ee47f20515a10..3688f79c16689f 100644 --- a/src/plugins/data_view_field_editor/public/types.ts +++ b/src/plugins/data_view_field_editor/public/types.ts @@ -17,8 +17,9 @@ import { DataViewsPublicPluginStart, FieldFormatsStart, RuntimeField, - RuntimeType, UsageCollectionStart, + RuntimeType, + SerializedFieldFormat, } from './shared_imports'; /** @@ -35,14 +36,27 @@ export interface PluginSetup { */ export interface PluginStart { /** - * method to open the data view field editor fly-out + * Method to open the data view field editor fly-out */ openEditor(options: OpenFieldEditorOptions): () => void; + /** + * Method to open the data view field delete fly-out + * @param options Configuration options for the fly-out + */ openDeleteModal(options: OpenFieldDeleteModalOptions): () => void; fieldFormatEditors: FormatEditorServiceStart['fieldFormatEditors']; + /** + * Convenience method for user permissions checks + */ userPermissions: { + /** + * Whether the user has permission to edit data views + */ editIndexPattern: () => boolean; }; + /** + * Context provider for delete runtime field modal + */ DeleteRuntimeFieldProvider: FunctionComponent<DeleteFieldProviderProps>; } @@ -62,33 +76,21 @@ export type InternalFieldType = 'concrete' | 'runtime'; * The data model for the field editor * @public */ -export interface Field { +export interface Field extends RuntimeField { /** * name / path used for the field */ name: FieldSpec['name']; /** - * ES type + * Name of parent field. Used for composite subfields */ - type: RuntimeType; - /** - * source of the runtime field script - */ - script?: RuntimeField['script']; - /** - * custom label for display - */ - customLabel?: FieldSpec['customLabel']; - /** - * custom popularity - */ - popularity?: number; - /** - * configuration of the field format - */ - format?: FieldSpec['format']; + parentName?: string; } +export interface FieldFormatConfig { + id: string; + params?: SerializedFieldFormat['params']; +} export interface EsRuntimeField { type: RuntimeType | string; script?: { diff --git a/src/plugins/data_view_field_editor/server/routes/field_preview.ts b/src/plugins/data_view_field_editor/server/routes/field_preview.ts index 6423694f76ec97..bee5fc0dbd1bef 100644 --- a/src/plugins/data_view_field_editor/server/routes/field_preview.ts +++ b/src/plugins/data_view_field_editor/server/routes/field_preview.ts @@ -24,6 +24,7 @@ const bodySchema = schema.object({ schema.literal('ip_field'), schema.literal('keyword_field'), schema.literal('long_field'), + schema.literal('composite_field'), ]), document: schema.object({}, { unknowns: 'allow' }), }); diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx index 3c9eeaa63109d6..208871f77022ae 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx @@ -20,13 +20,14 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; +import { DataView, DataViewField, RuntimeField } from '@kbn/data-views-plugin/public'; import { DATA_VIEW_SAVED_OBJECT_TYPE } from '@kbn/data-views-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { SavedObjectRelation, SavedObjectManagementTypeInfo, } from '@kbn/saved-objects-management-plugin/public'; +import { pickBy } from 'lodash'; import { IndexPatternManagmentContext } from '../../types'; import { Tabs } from './tabs'; import { IndexHeader } from './index_header'; @@ -61,11 +62,17 @@ const securityDataView = i18n.translate( const securitySolution = 'security-solution'; +const getCompositeRuntimeFields = (dataView: DataView) => + pickBy(dataView.getAllRuntimeFields(), (fld) => fld.type === 'composite'); + export const EditIndexPattern = withRouter( ({ indexPattern, history, location }: EditIndexPatternProps) => { const { uiSettings, overlays, chrome, dataViews, IndexPatternEditor, savedObjectsManagement } = useKibana<IndexPatternManagmentContext>().services; const [fields, setFields] = useState<DataViewField[]>(indexPattern.getNonScriptedFields()); + const [compositeRuntimeFields, setCompositeRuntimeFields] = useState< + Record<string, RuntimeField> + >(() => getCompositeRuntimeFields(indexPattern)); const [conflictedFields, setConflictedFields] = useState<DataViewField[]>( indexPattern.fields.getAll().filter((field) => field.type === 'conflict') ); @@ -250,8 +257,10 @@ export const EditIndexPattern = withRouter( allowedTypes={allowedTypes} history={history} location={location} + compositeRuntimeFields={compositeRuntimeFields} refreshFields={() => { setFields(indexPattern.getNonScriptedFields()); + setCompositeRuntimeFields(getCompositeRuntimeFields(indexPattern)); }} /> {displayIndexPatternEditor} diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/__snapshots__/table.test.tsx.snap b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/__snapshots__/table.test.tsx.snap index c054b42f51ac75..e06bcf99e3399b 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/__snapshots__/table.test.tsx.snap +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/__snapshots__/table.test.tsx.snap @@ -93,11 +93,7 @@ exports[`Table render name 2`] = ` <span>   <EuiIconTip - content={ - <span> - This field exists on the data view only. - </span> - } + content="This field exists on the data view only." title="Runtime field" type="indexRuntime" /> diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx index 1646ec0f24ed5b..ab6e82b301f012 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/components/table/table.tsx @@ -34,7 +34,10 @@ import { DataView } from '@kbn/data-views-plugin/public'; import { IndexedFieldItem } from '../../types'; export const showDelete = (field: IndexedFieldItem) => - !field.isMapped && field.isUserEditable && field.runtimeField?.type !== 'composite'; + // runtime fields that aren't composite subfields + (!field.isMapped && field.isUserEditable && field.runtimeField?.type !== 'composite') || + // composite runtime field definitions + (field.runtimeField?.type === 'composite' && field.type === 'composite'); // localized labels const additionalInfoAriaLabel = i18n.translate( @@ -161,10 +164,29 @@ const labelDescription = i18n.translate( { defaultMessage: 'A custom label for the field.' } ); -const runtimeIconTipTitle = i18n.translate( - 'indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipTitle', - { defaultMessage: 'Runtime field' } -); +function runtimeIconTipTitle(fld: IndexedFieldItem) { + // composite runtime fields + if (fld.runtimeField?.type === 'composite') { + // subfields definitions + if (fld.type !== 'composite') { + return i18n.translate( + 'indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipTitleCompositeSubfield', + { defaultMessage: 'Composite runtime subfield' } + ); + // composite definitions + } else { + return i18n.translate( + 'indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipTitleComposite', + { defaultMessage: 'Composite runtime field' } + ); + } + } + + return i18n.translate( + 'indexPatternManagement.editIndexPattern.fields.table.runtimeIconTipTitle', + { defaultMessage: 'Runtime field' } + ); +} const runtimeIconTipText = i18n.translate( 'indexPatternManagement.editDataView.fields.table.runtimeIconTipText', @@ -180,7 +202,7 @@ interface IndexedFieldProps { indexPattern: DataView; items: IndexedFieldItem[]; editField: (field: IndexedFieldItem) => void; - deleteField: (fieldName: string) => void; + deleteField: (fieldName: string[]) => void; openModal: OverlayModalStart['open']; theme: ThemeServiceStart; } @@ -229,8 +251,8 @@ export const renderFieldName = (field: IndexedFieldItem, timeFieldName?: string)   <EuiIconTip type="indexRuntime" - title={runtimeIconTipTitle} - content={<span>{runtimeIconTipText}</span>} + title={runtimeIconTipTitle(field)} + content={runtimeIconTipText} /> </span> ) : null} @@ -454,7 +476,16 @@ export class Table extends PureComponent<IndexedFieldProps> { name: deleteLabel, description: deleteDescription, icon: 'trash', - onClick: (field) => deleteField(field.name), + onClick: (field) => { + const toDelete = [field.name]; + if (field.spec?.runtimeField?.fields) { + const childFieldNames = Object.keys(field.spec.runtimeField.fields).map( + (key) => `${field.name}.${key}` + ); + toDelete.push(...childFieldNames); + } + deleteField(toDelete); + }, type: 'icon', 'data-test-subj': 'deleteField', available: showDelete, diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx index 4cc5792ce756bc..01ffc9377d8b21 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.test.tsx @@ -29,7 +29,7 @@ jest.mock('./components/table', () => ({ const helpers = { editField: (fieldName: string) => {}, - deleteField: (fieldName: string) => {}, + deleteField: (fieldName: string[]) => {}, // getFieldInfo handles non rollups as well getFieldInfo, }; @@ -118,6 +118,7 @@ describe('IndexedFieldsTable', () => { indexedFieldTypeFilter={[]} schemaFieldTypeFilter={[]} fieldFilter="" + compositeRuntimeFields={{}} {...mockedServices} /> ); @@ -140,6 +141,7 @@ describe('IndexedFieldsTable', () => { indexedFieldTypeFilter={[]} schemaFieldTypeFilter={[]} fieldFilter="" + compositeRuntimeFields={{}} {...mockedServices} /> ); @@ -163,6 +165,7 @@ describe('IndexedFieldsTable', () => { indexedFieldTypeFilter={[]} schemaFieldTypeFilter={[]} fieldFilter="" + compositeRuntimeFields={{}} {...mockedServices} /> ); @@ -186,6 +189,7 @@ describe('IndexedFieldsTable', () => { indexedFieldTypeFilter={[]} schemaFieldTypeFilter={[]} fieldFilter="" + compositeRuntimeFields={{}} {...mockedServices} /> ); @@ -210,6 +214,7 @@ describe('IndexedFieldsTable', () => { indexedFieldTypeFilter={[]} schemaFieldTypeFilter={[]} fieldFilter="" + compositeRuntimeFields={{}} {...mockedServices} /> ); diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx index e4326439e574a1..2a06f0c88b54f3 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/indexed_fields_table/indexed_fields_table.tsx @@ -9,7 +9,7 @@ import React, { Component } from 'react'; import { createSelector } from 'reselect'; import { OverlayStart, ThemeServiceStart } from '@kbn/core/public'; -import { DataViewField, DataView } from '@kbn/data-views-plugin/public'; +import { DataViewField, DataView, RuntimeField } from '@kbn/data-views-plugin/public'; import { Table } from './components/table'; import { IndexedFieldItem } from './types'; @@ -21,13 +21,14 @@ interface IndexedFieldsTableProps { schemaFieldTypeFilter: string[]; helpers: { editField: (fieldName: string) => void; - deleteField: (fieldName: string) => void; + deleteField: (fieldName: string[]) => void; getFieldInfo: (indexPattern: DataView, field: DataViewField) => string[]; }; fieldWildcardMatcher: (filters: string[] | undefined) => (val: string) => boolean; userEditPermission: boolean; openModal: OverlayStart['openModal']; theme: ThemeServiceStart; + compositeRuntimeFields: Record<string, RuntimeField>; } interface IndexedFieldsTableState { @@ -42,14 +43,23 @@ export class IndexedFieldsTable extends Component< super(props); this.state = { - fields: this.mapFields(this.props.fields), + fields: [ + ...this.mapCompositeRuntimeFields(this.props.compositeRuntimeFields), + ...this.mapFields(this.props.fields), + ], }; } UNSAFE_componentWillReceiveProps(nextProps: IndexedFieldsTableProps) { - if (nextProps.fields !== this.props.fields) { + if ( + nextProps.fields !== this.props.fields || + nextProps.compositeRuntimeFields !== this.props.compositeRuntimeFields + ) { this.setState({ - fields: this.mapFields(nextProps.fields), + fields: [ + ...this.mapCompositeRuntimeFields(nextProps.compositeRuntimeFields), + ...this.mapFields(nextProps.fields), + ], }); } } @@ -57,7 +67,8 @@ export class IndexedFieldsTable extends Component< mapFields(fields: DataViewField[]): IndexedFieldItem[] { const { indexPattern, fieldWildcardMatcher, helpers, userEditPermission } = this.props; const sourceFilters = - indexPattern.sourceFilters && indexPattern.sourceFilters.map((f) => f.value); + indexPattern.sourceFilters && + indexPattern.sourceFilters.map((f: Record<string, any>) => f.value); const fieldWildcardMatch = fieldWildcardMatcher(sourceFilters || []); return ( @@ -80,6 +91,46 @@ export class IndexedFieldsTable extends Component< ); } + mapCompositeRuntimeFields( + compositeRuntimeFields: Record<string, RuntimeField> + ): IndexedFieldItem[] { + const { indexPattern, fieldWildcardMatcher, userEditPermission } = this.props; + const sourceFilters = + indexPattern.sourceFilters && + indexPattern.sourceFilters.map((f: Record<string, any>) => f.value); + const fieldWildcardMatch = fieldWildcardMatcher(sourceFilters || []); + + return Object.entries(compositeRuntimeFields).map(([name, fld]) => { + return { + spec: { + searchable: false, + aggregatable: false, + name, + type: 'composite', + runtimeField: { + type: 'composite', + script: fld.script, + fields: fld.fields, + }, + }, + name, + type: 'composite', + kbnType: '', + displayName: name, + excluded: fieldWildcardMatch ? fieldWildcardMatch(name) : false, + info: [], + isMapped: false, + isUserEditable: userEditPermission, + hasRuntime: true, + runtimeField: { + type: 'composite', + script: fld.script, + fields: fld.fields, + }, + }; + }); + } + getFilteredFields = createSelector( (state: IndexedFieldsTableState) => state.fields, (_state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.fieldFilter, @@ -135,14 +186,13 @@ export class IndexedFieldsTable extends Component< render() { const { indexPattern } = this.props; const fields = this.getFilteredFields(this.state, this.props); - return ( <div> <Table indexPattern={indexPattern} items={fields} editField={(field) => this.props.helpers.editField(field.name)} - deleteField={(fieldName) => this.props.helpers.deleteField(fieldName)} + deleteField={(fieldNames) => this.props.helpers.deleteField(fieldNames)} openModal={this.props.openModal} theme={this.props.theme} /> diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx index a4b87110521d71..075869ab6fdc22 100644 --- a/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx +++ b/src/plugins/data_view_management/public/components/edit_index_pattern/tabs/tabs.tsx @@ -29,6 +29,7 @@ import { DataViewField, DataViewsPublicPluginStart, META_FIELDS, + RuntimeField, } from '@kbn/data-views-plugin/public'; import { SavedObjectRelation, @@ -57,6 +58,7 @@ interface TabsProps extends Pick<RouteComponentProps, 'history' | 'location'> { refreshFields: () => void; relationships: SavedObjectRelation[]; allowedTypes: SavedObjectManagementTypeInfo[]; + compositeRuntimeFields: Record<string, RuntimeField>; } interface FilterItems { @@ -144,6 +146,7 @@ export function Tabs({ refreshFields, relationships, allowedTypes, + compositeRuntimeFields, }: TabsProps) { const { uiSettings, @@ -462,6 +465,7 @@ export function Tabs({ {(deleteField) => ( <IndexedFieldsTable fields={fields} + compositeRuntimeFields={compositeRuntimeFields} indexPattern={indexPattern} fieldFilter={fieldFilter} fieldWildcardMatcher={fieldWildcardMatcherDecorated} @@ -554,6 +558,7 @@ export function Tabs({ overlays, theme, dataViews, + compositeRuntimeFields, http, application, savedObjectsManagement, diff --git a/src/plugins/data_views/common/data_views/data_view.test.ts b/src/plugins/data_views/common/data_views/data_view.test.ts index c693e1a1702100..25966a1d9fc857 100644 --- a/src/plugins/data_views/common/data_views/data_view.test.ts +++ b/src/plugins/data_views/common/data_views/data_view.test.ts @@ -7,13 +7,14 @@ */ import { FieldFormat } from '@kbn/field-formats-plugin/common'; + +import { RuntimeField, RuntimePrimitiveTypes, FieldSpec } from '../types'; +import { stubLogstashFields } from '../field.stub'; import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; import { CharacterNotAllowedInField } from '@kbn/kibana-utils-plugin/common'; import { last, map } from 'lodash'; import { stubbedSavedObjectIndexPattern } from '../data_view.stub'; -import { stubLogstashFields } from '../field.stub'; import { DataViewField } from '../fields'; -import { FieldSpec, RuntimeField, RuntimeTypeExceptComposite } from '../types'; import { DataView } from './data_view'; class MockFieldFormatter {} @@ -262,10 +263,10 @@ describe('IndexPattern', () => { }, fields: { a: { - type: 'keyword' as RuntimeTypeExceptComposite, + type: 'keyword' as RuntimePrimitiveTypes, }, b: { - type: 'long' as RuntimeTypeExceptComposite, + type: 'long' as RuntimePrimitiveTypes, }, }, }; diff --git a/src/plugins/data_views/common/data_views/data_views.ts b/src/plugins/data_views/common/data_views/data_views.ts index 7c5e9314a153e8..892df9b312e86d 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -784,7 +784,8 @@ export class DataViewsService { const addRuntimeFieldToSpecFields = ( name: string, fieldType: RuntimeType, - runtimeField: RuntimeFieldSpec + runtimeField: RuntimeFieldSpec, + parentName?: string ) => { spec[name] = { name, @@ -797,6 +798,10 @@ export class DataViewsService { customLabel: fieldAttrs?.[name]?.customLabel, count: fieldAttrs?.[name]?.count, }; + + if (parentName) { + spec[name].parentName = parentName; + } }; // CREATE RUNTIME FIELDS @@ -804,7 +809,7 @@ export class DataViewsService { // For composite runtime field we add the subFields, **not** the composite if (runtimeField.type === 'composite') { Object.entries(runtimeField.fields!).forEach(([subFieldName, subField]) => { - addRuntimeFieldToSpecFields(`${name}.${subFieldName}`, subField.type, runtimeField); + addRuntimeFieldToSpecFields(`${name}.${subFieldName}`, subField.type, runtimeField, name); }); } else { addRuntimeFieldToSpecFields(name, runtimeField.type, runtimeField); diff --git a/src/plugins/data_views/common/data_views/utils.ts b/src/plugins/data_views/common/data_views/utils.ts index 31a6b573ff2b3c..a5d0447f793392 100644 --- a/src/plugins/data_views/common/data_views/utils.ts +++ b/src/plugins/data_views/common/data_views/utils.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { RuntimeField, RuntimeFieldSpec, RuntimeTypeExceptComposite } from '../types'; +import type { RuntimeField, RuntimeFieldSpec, RuntimePrimitiveTypes } from '../types'; export const removeFieldAttrs = (runtimeField: RuntimeField): RuntimeFieldSpec => { const { type, script, fields } = runtimeField; @@ -14,7 +14,7 @@ export const removeFieldAttrs = (runtimeField: RuntimeField): RuntimeFieldSpec = fields: Object.entries(fields).reduce((col, [fieldName, field]) => { col[fieldName] = { type: field.type }; return col; - }, {} as Record<string, { type: RuntimeTypeExceptComposite }>), + }, {} as Record<string, { type: RuntimePrimitiveTypes }>), }; return { diff --git a/src/plugins/data_views/common/index.ts b/src/plugins/data_views/common/index.ts index ffeeb069d19121..5f7b3a544db9df 100644 --- a/src/plugins/data_views/common/index.ts +++ b/src/plugins/data_views/common/index.ts @@ -27,9 +27,11 @@ export { export type { FieldFormatMap, RuntimeType, + RuntimePrimitiveTypes, RuntimeField, RuntimeFieldSpec, RuntimeFieldSubField, + RuntimeFieldSubFields, DataViewAttributes, OnNotification, OnError, @@ -46,7 +48,6 @@ export type { DataViewSpec, SourceFilter, HasDataService, - RuntimeTypeExceptComposite, RuntimeFieldBase, FieldConfiguration, SavedObjectsClientCommonFindArgs, diff --git a/src/plugins/data_views/common/types.ts b/src/plugins/data_views/common/types.ts index ec0aeb081124eb..54c8c61635f630 100644 --- a/src/plugins/data_views/common/types.ts +++ b/src/plugins/data_views/common/types.ts @@ -23,18 +23,14 @@ export type { SavedObject }; export type FieldFormatMap = Record<string, SerializedFieldFormat>; /** - * Runtime field - type of value returned - * @public + * Runtime field types */ - export type RuntimeType = typeof RUNTIME_FIELD_TYPES[number]; /** - * Primitive runtime field types - * @public + * Runtime field primitive types - excluding composite */ - -export type RuntimeTypeExceptComposite = Exclude<RuntimeType, 'composite'>; +export type RuntimePrimitiveTypes = Exclude<RuntimeType, 'composite'>; /** * Runtime field definition @@ -61,11 +57,14 @@ export type RuntimeFieldBase = { * The RuntimeField that will be sent in the ES Query "runtime_mappings" object */ export type RuntimeFieldSpec = RuntimeFieldBase & { + /** + * Composite subfields + */ fields?: Record< string, { // It is not recursive, we can't create a composite inside a composite. - type: RuntimeTypeExceptComposite; + type: RuntimePrimitiveTypes; } >; }; @@ -98,18 +97,18 @@ export interface RuntimeField extends RuntimeFieldBase, FieldConfiguration { /** * Subfields of composite field */ - fields?: Record<string, RuntimeFieldSubField>; + fields?: RuntimeFieldSubFields; } +export type RuntimeFieldSubFields = Record<string, RuntimeFieldSubField>; + /** * Runtime field composite subfield * @public */ export interface RuntimeFieldSubField extends FieldConfiguration { - /** - * Type of runtime field, can only be primitive type - */ - type: RuntimeTypeExceptComposite; + // It is not recursive, we can't create a composite inside a composite. + type: RuntimePrimitiveTypes; } /** @@ -448,6 +447,10 @@ export type FieldSpec = DataViewFieldBase & { * Is this field in the mapping? False if a scripted or runtime field defined on the data view. */ isMapped?: boolean; + /** + * Name of parent field for composite runtime field subfields. + */ + parentName?: string; }; export type DataViewFieldMap = Record<string, FieldSpec>; diff --git a/src/plugins/data_views/public/index.ts b/src/plugins/data_views/public/index.ts index cf48aaee81fd04..f886d60696b8aa 100644 --- a/src/plugins/data_views/public/index.ts +++ b/src/plugins/data_views/public/index.ts @@ -20,6 +20,7 @@ export type { FieldSpec, DataViewAttributes, SavedObjectsClientCommon, + RuntimeField, } from '../common'; export { DataViewField, diff --git a/test/functional/apps/management/_runtime_fields_composite.ts b/test/functional/apps/management/_runtime_fields_composite.ts new file mode 100644 index 00000000000000..47ea33e443d225 --- /dev/null +++ b/test/functional/apps/management/_runtime_fields_composite.ts @@ -0,0 +1,90 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); + const log = getService('log'); + const browser = getService('browser'); + const retry = getService('retry'); + const PageObjects = getPageObjects(['settings']); + const testSubjects = getService('testSubjects'); + + describe('runtime fields', function () { + this.tags(['skipFirefox']); + + before(async function () { + await browser.setWindowSize(1200, 800); + await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover'); + await kibanaServer.uiSettings.replace({}); + }); + + after(async function afterAll() { + await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover'); + }); + + describe('create composite runtime field', function describeIndexTests() { + // Starting with '@' to sort toward start of field list + const fieldName = '@composite_test'; + + it('should create runtime field', async function () { + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaIndexPatterns(); + await PageObjects.settings.clickIndexPatternLogstash(); + const startingCount = parseInt(await PageObjects.settings.getFieldsTabCount(), 10); + await log.debug('add runtime field'); + await PageObjects.settings.addCompositeRuntimeField( + fieldName, + "emit('a','hello world')", + false, + 1 + ); + + await log.debug('check that field preview is rendered'); + expect(await testSubjects.exists('fieldPreviewItem', { timeout: 1500 })).to.be(true); + + await PageObjects.settings.clickSaveField(); + + await retry.try(async function () { + expect(parseInt(await PageObjects.settings.getFieldsTabCount(), 10)).to.be( + startingCount + 1 + ); + }); + }); + + it('should modify runtime field', async function () { + const startingCount = parseInt(await PageObjects.settings.getFieldsTabCount(), 10); + await PageObjects.settings.filterField(fieldName); + await testSubjects.click('editFieldFormat'); + // wait for subfields to render + await testSubjects.find(`typeField_0`); + await new Promise((e) => setTimeout(e, 2000)); + await PageObjects.settings.setCompositeScript("emit('a',6);emit('b',10);"); + + // wait for subfields to render + await testSubjects.find(`typeField_1`); + await new Promise((e) => setTimeout(e, 500)); + + await PageObjects.settings.clickSaveField(); + await testSubjects.click('clearSearchButton'); + await retry.try(async function () { + expect(parseInt(await PageObjects.settings.getFieldsTabCount(), 10)).to.be( + startingCount + 1 + ); + }); + }); + + it('should delete runtime field', async function () { + await testSubjects.click('deleteField'); + await PageObjects.settings.confirmDelete(); + }); + }); + }); +} diff --git a/test/functional/apps/management/index.ts b/test/functional/apps/management/index.ts index ded50870d79567..9b905b5a010743 100644 --- a/test/functional/apps/management/index.ts +++ b/test/functional/apps/management/index.ts @@ -32,6 +32,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_scripted_fields')); loadTestFile(require.resolve('./_scripted_fields_classic_table')); loadTestFile(require.resolve('./_runtime_fields')); + loadTestFile(require.resolve('./_runtime_fields_composite')); loadTestFile(require.resolve('./_field_formatter')); loadTestFile(require.resolve('./_legacy_url_redirect')); loadTestFile(require.resolve('./_exclude_index_pattern')); diff --git a/test/functional/page_objects/settings_page.ts b/test/functional/page_objects/settings_page.ts index ab47fb31fea54d..b0f2efea409933 100644 --- a/test/functional/page_objects/settings_page.ts +++ b/test/functional/page_objects/settings_page.ts @@ -700,6 +700,25 @@ export class SettingsPageObject extends FtrService { if (script) { await this.setFieldScript(script); } + + if (doSaveField) { + await this.clickSaveField(); + } + } + + async addCompositeRuntimeField( + name: string, + script: string, + doSaveField = true, + subfieldCount = 0 + ) { + await this.clickAddField(); + await this.setFieldName(name); + await this.setFieldTypeComposite(); + await this.setCompositeScript(script); + if (subfieldCount > 0) { + await this.testSubjects.find(`typeField_${subfieldCount - 1}`); + } if (doSaveField) { await this.clickSaveField(); } @@ -765,6 +784,12 @@ export class SettingsPageObject extends FtrService { await this.testSubjects.setValue('typeField', type); } + async setFieldTypeComposite() { + this.log.debug('set type = Composite'); + await this.testSubjects.setValue('typeField', 'Composite'); + await this.browser.pressKeys(this.browser.keys.RETURN); + } + async setFieldScript(script: string) { this.log.debug('set script = ' + script); await this.toggleRow('valueRow'); @@ -772,6 +797,12 @@ export class SettingsPageObject extends FtrService { await this.monacoEditor.setCodeEditorValue(script); } + async setCompositeScript(script: string) { + this.log.debug('set composite script = ' + script); + await this.monacoEditor.waitCodeEditorReady('scriptFieldRow'); + await this.monacoEditor.setCodeEditorValue(script); + } + async clickAddScriptedField() { this.log.debug('click Add Scripted Field'); await this.testSubjects.click('addScriptedFieldLink'); diff --git a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx index 96ed68d32398db..0f7a5e0625216b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.test.tsx @@ -185,7 +185,7 @@ describe('useFieldBrowserOptions', () => { }); it('should dispatch the proper action when a new field is saved', async () => { - let onSave: ((field: DataViewField) => void) | undefined; + let onSave: ((field: DataViewField[]) => void) | undefined; useKibanaMock().services.data.dataViews.get = () => Promise.resolve({} as DataView); useKibanaMock().services.dataViewFieldEditor.openEditor = (options) => { onSave = options.onSave; @@ -202,7 +202,7 @@ describe('useFieldBrowserOptions', () => { getByRole('button').click(); expect(onSave).toBeDefined(); - const savedField = { name: 'newField' } as DataViewField; + const savedField = [{ name: 'newField' }] as DataViewField[]; onSave!(savedField); await runAllPromises(); @@ -213,7 +213,7 @@ describe('useFieldBrowserOptions', () => { id: TimelineId.test, column: { columnHeaderType: defaultColumnHeaderType, - id: savedField.name, + id: savedField[0].name, initialWidth: DEFAULT_COLUMN_MIN_WIDTH, }, index: 0, @@ -222,7 +222,7 @@ describe('useFieldBrowserOptions', () => { }); it('should dispatch the proper actions when a field is edited', async () => { - let onSave: ((field: DataViewField) => void) | undefined; + let onSave: ((field: DataViewField[]) => void) | undefined; useKibanaMock().services.data.dataViews.get = () => Promise.resolve({} as DataView); useKibanaMock().services.dataViewFieldEditor.openEditor = (options) => { onSave = options.onSave; @@ -243,7 +243,7 @@ describe('useFieldBrowserOptions', () => { getByTestId('actionEditRuntimeField').click(); expect(onSave).toBeDefined(); - const savedField = { name: `new ${fieldItem.name}` } as DataViewField; + const savedField = [{ name: `new ${fieldItem.name}` }] as DataViewField[]; onSave!(savedField); await runAllPromises(); @@ -260,7 +260,7 @@ describe('useFieldBrowserOptions', () => { id: TimelineId.test, column: { columnHeaderType: defaultColumnHeaderType, - id: savedField.name, + id: savedField[0].name, initialWidth: DEFAULT_COLUMN_MIN_WIDTH, }, index: 0, diff --git a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx index d15fd7a501ea09..9fb4f2b13adb72 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/fields_browser/index.tsx @@ -77,35 +77,36 @@ export const useFieldBrowserOptions: UseFieldBrowserOptions = ({ const closeFieldEditor = dataViewFieldEditor.openEditor({ ctx: { dataView }, fieldName, - onSave: async (savedField: DataViewField) => { + onSave: async (savedFields: DataViewField[]) => { startTransaction({ name: FIELD_BROWSER_ACTIONS.FIELD_SAVED }); - // Fetch the updated list of fields // Using cleanCache since the number of fields might have not changed, but we need to update the state anyway await indexFieldsSearch({ dataViewId: selectedDataViewId, cleanCache: true }); - if (fieldName && fieldName !== savedField.name) { - // Remove old field from event table when renaming a field + for (const savedField of savedFields) { + if (fieldName && fieldName !== savedField.name) { + // Remove old field from event table when renaming a field + dispatch( + removeColumn({ + columnId: fieldName, + id: timelineId, + }) + ); + } + + // Add the saved column field to the table in any case dispatch( - removeColumn({ - columnId: fieldName, + upsertColumn({ + column: { + columnHeaderType: defaultColumnHeaderType, + id: savedField.name, + initialWidth: DEFAULT_COLUMN_MIN_WIDTH, + }, id: timelineId, + index: 0, }) ); } - - // Add the saved column field to the table in any case - dispatch( - upsertColumn({ - column: { - columnHeaderType: defaultColumnHeaderType, - id: savedField.name, - initialWidth: DEFAULT_COLUMN_MIN_WIDTH, - }, - id: timelineId, - index: 0, - }) - ); if (editorActionsRef) { editorActionsRef.current = null; } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 3e1a916085b401..a7aadfb61248ad 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -31665,7 +31665,6 @@ "xpack.transform.home.breadcrumbTitle": "Transformations", "xpack.transform.indexPreview.copyClipboardTooltip": "Copier la déclaration Dev Console de l'aperçu de l'index dans le presse-papiers.", "xpack.transform.indexPreview.copyRuntimeFieldsClipboardTooltip": "Copier la déclaration Dev Console des champs de temps d'exécution dans le presse-papiers.", - "xpack.transform.invalidRuntimeFieldMessage": "Champ d'exécution non valide", "xpack.transform.latestPreview.latestPreviewIncompleteConfigCalloutBody": "Veuillez choisir au moins une clé unique et un champ de tri.", "xpack.transform.licenseCheckErrorMessage": "La vérification de la licence a échoué", "xpack.transform.list.emptyPromptButtonText": "Créez votre première transformation", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 6c875ca0c23330..fd4a320e417e14 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -31642,7 +31642,6 @@ "xpack.transform.home.breadcrumbTitle": "変換", "xpack.transform.indexPreview.copyClipboardTooltip": "インデックスプレビューの開発コンソールステートメントをクリップボードにコピーします。", "xpack.transform.indexPreview.copyRuntimeFieldsClipboardTooltip": "ランタイムフィールドの開発コンソールステートメントをクリップボードにコピーします。", - "xpack.transform.invalidRuntimeFieldMessage": "無効なランタイムフィールド", "xpack.transform.latestPreview.latestPreviewIncompleteConfigCalloutBody": "1 つ以上の一意キーと並べ替えフィールドを選択してください。", "xpack.transform.licenseCheckErrorMessage": "ライセンス確認失敗", "xpack.transform.list.emptyPromptButtonText": "初めての変換を作成してみましょう。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 05d1f7e1f51e85..8002605d93758e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -31675,7 +31675,6 @@ "xpack.transform.home.breadcrumbTitle": "转换", "xpack.transform.indexPreview.copyClipboardTooltip": "将索引预览的开发控制台语句复制到剪贴板。", "xpack.transform.indexPreview.copyRuntimeFieldsClipboardTooltip": "将运行时字段的开发控制台语句复制到剪贴板。", - "xpack.transform.invalidRuntimeFieldMessage": "运行时字段无效", "xpack.transform.latestPreview.latestPreviewIncompleteConfigCalloutBody": "请选择至少一个唯一键和排序字段。", "xpack.transform.licenseCheckErrorMessage": "许可证检查失败", "xpack.transform.list.emptyPromptButtonText": "创建您的首个转换", From 3a361ad29c8fea81da399846f00cce60ab98bb24 Mon Sep 17 00:00:00 2001 From: Christos Nasikas <christos.nasikas@elastic.co> Date: Mon, 12 Sep 2022 16:43:50 +0300 Subject: [PATCH 062/144] [Cases] Fix attachment success toaster navigation url (#140116) * Fix toaster navigation url * Add tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/cases/common/constants.ts | 3 + .../public/common/use_cases_toast.test.tsx | 71 ++++++++++++++++++- .../cases/public/common/use_cases_toast.tsx | 26 +++++-- 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/cases/common/constants.ts b/x-pack/plugins/cases/common/constants.ts index ccc4ada609d037..a0488094283d0b 100644 --- a/x-pack/plugins/cases/common/constants.ts +++ b/x-pack/plugins/cases/common/constants.ts @@ -103,14 +103,17 @@ export const GENERAL_CASES_OWNER = APP_ID; export const OWNER_INFO = { [SECURITY_SOLUTION_OWNER]: { + appId: 'securitySolutionUI', label: 'Security', iconType: 'logoSecurity', }, [OBSERVABILITY_OWNER]: { + appId: 'observability-overview', label: 'Observability', iconType: 'logoObservability', }, [GENERAL_CASES_OWNER]: { + appId: 'management', label: 'Stack', iconType: 'casesApp', }, diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx index c764df4d6661d7..e8661387e1e649 100644 --- a/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx +++ b/x-pack/plugins/cases/public/common/use_cases_toast.test.tsx @@ -6,20 +6,25 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { useToasts } from './lib/kibana'; +import { useKibana, useToasts } from './lib/kibana'; import { AppMockRenderer, createAppMockRenderer, TestProviders } from './mock'; import { CaseToastSuccessContent, useCasesToast } from './use_cases_toast'; import { alertComment, basicComment, mockCase } from '../containers/mock'; import React from 'react'; import userEvent from '@testing-library/user-event'; import { SupportedCaseAttachment } from '../types'; +import { getByTestId } from '@testing-library/dom'; +import { OWNER_INFO } from '../../common/constants'; jest.mock('./lib/kibana'); const useToastsMock = useToasts as jest.Mock; +const useKibanaMock = useKibana as jest.Mocked<typeof useKibana>; describe('Use cases toast hook', () => { const successMock = jest.fn(); + const getUrlForApp = jest.fn().mockReturnValue(`/app/cases/${mockCase.id}`); + const navigateToUrl = jest.fn(); function validateTitle(title: string) { const mockParams = successMock.mock.calls[0][0]; @@ -35,6 +40,14 @@ describe('Use cases toast hook', () => { expect(el).toHaveTextContent(content); } + function navigateToCase() { + const mockParams = successMock.mock.calls[0][0]; + const el = document.createElement('div'); + mockParams.text(el); + const button = getByTestId(el, 'toaster-content-case-view-link'); + userEvent.click(button); + } + useToastsMock.mockImplementation(() => { return { addSuccess: successMock, @@ -42,7 +55,12 @@ describe('Use cases toast hook', () => { }); beforeEach(() => { - successMock.mockClear(); + jest.clearAllMocks(); + useKibanaMock().services.application = { + ...useKibanaMock().services.application, + getUrlForApp, + navigateToUrl, + }; }); describe('Toast hook', () => { @@ -119,6 +137,7 @@ describe('Use cases toast hook', () => { validateTitle('Another horrible breach!! has been updated'); }); }); + describe('Toast content', () => { let appMockRender: AppMockRenderer; const onViewCaseClick = jest.fn(); @@ -192,4 +211,52 @@ describe('Use cases toast hook', () => { expect(onViewCaseClick).toHaveBeenCalled(); }); }); + + describe('Toast navigation', () => { + const tests = Object.entries(OWNER_INFO).map(([owner, ownerInfo]) => [owner, ownerInfo.appId]); + + it.each(tests)('should navigate correctly with owner %s and appId %s', (owner, appId) => { + const { result } = renderHook( + () => { + return useCasesToast(); + }, + { wrapper: TestProviders } + ); + + result.current.showSuccessAttach({ + theCase: { ...mockCase, owner }, + title: 'Custom title', + }); + + navigateToCase(); + + expect(getUrlForApp).toHaveBeenCalledWith(appId, { + deepLinkId: 'cases', + path: '/mock-id', + }); + + expect(navigateToUrl).toHaveBeenCalledWith('/app/cases/mock-id'); + }); + + it('navigates to the current app if the owner is invalid', () => { + const { result } = renderHook( + () => { + return useCasesToast(); + }, + { wrapper: TestProviders } + ); + + result.current.showSuccessAttach({ + theCase: { ...mockCase, owner: 'in-valid' }, + title: 'Custom title', + }); + + navigateToCase(); + + expect(getUrlForApp).toHaveBeenCalledWith('testAppId', { + deepLinkId: 'cases', + path: '/mock-id', + }); + }); + }); }); diff --git a/x-pack/plugins/cases/public/common/use_cases_toast.tsx b/x-pack/plugins/cases/public/common/use_cases_toast.tsx index 5e88831144b6b8..7d445a4edffac9 100644 --- a/x-pack/plugins/cases/public/common/use_cases_toast.tsx +++ b/x-pack/plugins/cases/public/common/use_cases_toast.tsx @@ -10,8 +10,8 @@ import React from 'react'; import styled from 'styled-components'; import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import { Case, CommentType } from '../../common'; -import { useToasts } from './lib/kibana'; -import { useCaseViewNavigation } from './navigation'; +import { useKibana, useToasts } from './lib/kibana'; +import { generateCaseViewPath } from './navigation'; import { CaseAttachmentsWithoutOwner } from '../types'; import { CASE_ALERT_SUCCESS_SYNC_TEXT, @@ -19,6 +19,8 @@ import { CASE_SUCCESS_TOAST, VIEW_CASE, } from './translations'; +import { OWNER_INFO } from '../../common/constants'; +import { useCasesContext } from '../components/cases_context/use_cases_context'; const LINE_CLAMP = 3; const Title = styled.span` @@ -93,8 +95,12 @@ function getToastContent({ return undefined; } +const isValidOwner = (owner: string): owner is keyof typeof OWNER_INFO => + Object.keys(OWNER_INFO).includes(owner); + export const useCasesToast = () => { - const { navigateToCaseView } = useCaseViewNavigation(); + const { appId } = useCasesContext(); + const { getUrlForApp, navigateToUrl } = useKibana().services.application; const toasts = useToasts(); @@ -110,11 +116,19 @@ export const useCasesToast = () => { title?: string; content?: string; }) => { + const appIdToNavigateTo = isValidOwner(theCase.owner) + ? OWNER_INFO[theCase.owner].appId + : appId; + + const url = getUrlForApp(appIdToNavigateTo, { + deepLinkId: 'cases', + path: generateCaseViewPath({ detailName: theCase.id }), + }); + const onViewCaseClick = () => { - navigateToCaseView({ - detailName: theCase.id, - }); + navigateToUrl(url); }; + const renderTitle = getToastTitle({ theCase, title, attachments }); const renderContent = getToastContent({ theCase, content, attachments }); From d2eae9fb874313d927d4d94d979b2c2f564e724e Mon Sep 17 00:00:00 2001 From: doakalexi <109488926+doakalexi@users.noreply.github.com> Date: Mon, 12 Sep 2022 09:45:29 -0400 Subject: [PATCH 063/144] Setting auto expand replicas (#140335) --- .../server/rule_data_plugin_service/resource_installer.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts index 2ed80cb02c0d3e..fdd0b1c931bd1e 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts @@ -337,6 +337,7 @@ export class ResourceInstaller { rollover_alias: primaryNamespacedAlias, }, 'index.mapping.total_fields.limit': 1700, + auto_expand_replicas: '0-1', }, mappings: { dynamic: false, From 2335e1e479f94530ff252189c0e37d211b81c4f8 Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Mon, 12 Sep 2022 09:55:57 -0400 Subject: [PATCH 064/144] [Security Solution] Render host isolation content in timeline side panel (#139881) * Render host isolation content in timeline side panel * New FTR suite for endpoint solution integrations * FTR Endpoint service: additional methods to update an endpoint metadata Co-authored-by: Paul Tavares <paul.tavares@elastic.co> Co-authored-by: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> --- .../endpoint/host_isolation/isolate_form.tsx | 2 +- .../host_isolation/unisolate_form.tsx | 8 +- .../side_panel/event_details/index.tsx | 208 ++++++++++++------ .../apps/endpoint/endpoint_list.ts | 20 +- .../endpoint_solution_integrations.ts | 103 +++++++++ .../apps/endpoint/index.ts | 1 + .../services/endpoint.ts | 94 +++++++- .../services/timeline/index.ts | 69 +++++- 8 files changed, 413 insertions(+), 92 deletions(-) create mode 100644 x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/isolate_form.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/isolate_form.tsx index ce1e1939ef1bbc..5bffe92e6d0199 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/isolate_form.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/isolate_form.tsx @@ -42,7 +42,7 @@ export const EndpointIsolateForm = memo<EndpointIsolatedFormProps>( ); return ( - <EuiForm> + <EuiForm data-test-subj="endpointHostIsolationForm"> <EuiFormRow fullWidth> <EuiText size="s"> <p> diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/unisolate_form.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/unisolate_form.tsx index 4e8358f3810fbd..8226175786ae07 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/unisolate_form.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/host_isolation/unisolate_form.tsx @@ -31,7 +31,7 @@ export const EndpointUnisolateForm = memo<EndpointIsolatedFormProps>( ); return ( - <EuiForm> + <EuiForm data-test-subj="endpointHostIsolationForm"> <EuiFormRow fullWidth> <EuiText size="s"> <p> @@ -62,7 +62,11 @@ export const EndpointUnisolateForm = memo<EndpointIsolatedFormProps>( <EuiFormRow fullWidth> <EuiFlexGroup justifyContent="flexEnd"> <EuiFlexItem grow={false}> - <EuiButtonEmpty onClick={onCancel} disabled={isLoading}> + <EuiButtonEmpty + onClick={onCancel} + disabled={isLoading} + data-test-subj="hostIsolateCancelButton" + > {CANCEL} </EuiButtonEmpty> </EuiFlexItem> diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx index 83e06db651e00e..00397ea43e59ab 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiSpacer } from '@elastic/eui'; +import { EuiSpacer, EuiFlyoutBody } from '@elastic/eui'; import React, { useMemo } from 'react'; import deepEqual from 'fast-deep-equal'; @@ -22,6 +22,8 @@ import { useHostIsolationTools } from './use_host_isolation_tools'; import { FlyoutBody, FlyoutHeader, FlyoutFooter } from './flyout'; import { useBasicDataFromDetailsData, getAlertIndexAlias } from './helpers'; import { useSpaceId } from '../../../../common/hooks/use_space_id'; +import { EndpointIsolateSuccess } from '../../../../common/components/endpoint/host_isolation'; +import { HostIsolationPanel } from '../../../../detections/components/host_isolation'; interface EventDetailsPanelProps { browserFields: BrowserFields; @@ -95,49 +97,144 @@ const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({ pagination, }); - const hostRisk: HostRisk | null = data - ? { - loading: hostRiskLoading, - isModuleEnabled, - result: data, - } - : null; + const hostRisk: HostRisk | null = useMemo(() => { + return data + ? { + loading: hostRiskLoading, + isModuleEnabled, + result: data, + } + : null; + }, [data, hostRiskLoading, isModuleEnabled]); + + const header = useMemo( + () => + isFlyoutView || isHostIsolationPanelOpen ? ( + <FlyoutHeader + isHostIsolationPanelOpen={isHostIsolationPanelOpen} + isAlert={isAlert} + isolateAction={isolateAction} + loading={loading} + ruleName={ruleName} + showAlertDetails={showAlertDetails} + timestamp={timestamp} + /> + ) : ( + <ExpandableEventTitle + isAlert={isAlert} + loading={loading} + ruleName={ruleName} + handleOnEventClosed={handleOnEventClosed} + /> + ), + [ + handleOnEventClosed, + isAlert, + isFlyoutView, + isHostIsolationPanelOpen, + isolateAction, + loading, + ruleName, + showAlertDetails, + timestamp, + ] + ); + + const body = useMemo(() => { + if (isFlyoutView) { + return ( + <FlyoutBody + alertId={alertId} + browserFields={browserFields} + detailsData={detailsData} + event={expandedEvent} + hostName={hostName} + hostRisk={hostRisk} + handleIsolationActionSuccess={handleIsolationActionSuccess} + handleOnEventClosed={handleOnEventClosed} + isAlert={isAlert} + isDraggable={isDraggable} + isolateAction={isolateAction} + isIsolateActionSuccessBannerVisible={isIsolateActionSuccessBannerVisible} + isHostIsolationPanelOpen={isHostIsolationPanelOpen} + loading={loading} + rawEventData={rawEventData} + showAlertDetails={showAlertDetails} + timelineId={timelineId} + isReadOnly={isReadOnly} + /> + ); + } else if (isHostIsolationPanelOpen) { + return ( + <> + {isIsolateActionSuccessBannerVisible && ( + <EndpointIsolateSuccess + hostName={hostName} + alertId={alertId} + isolateAction={isolateAction} + /> + )} + <EuiFlyoutBody> + <HostIsolationPanel + details={detailsData} + cancelCallback={showAlertDetails} + successCallback={handleIsolationActionSuccess} + isolateAction={isolateAction} + /> + </EuiFlyoutBody> + </> + ); + } else { + return ( + <> + <EuiSpacer size="m" /> + <ExpandableEvent + browserFields={browserFields} + detailsData={detailsData} + event={expandedEvent} + isAlert={isAlert} + isDraggable={isDraggable} + loading={loading} + rawEventData={rawEventData} + timelineId={timelineId} + timelineTabType={tabType} + hostRisk={hostRisk} + handleOnEventClosed={handleOnEventClosed} + /> + </> + ); + } + }, [ + alertId, + browserFields, + detailsData, + expandedEvent, + handleIsolationActionSuccess, + handleOnEventClosed, + hostName, + hostRisk, + isAlert, + isDraggable, + isFlyoutView, + isHostIsolationPanelOpen, + isIsolateActionSuccessBannerVisible, + isReadOnly, + isolateAction, + loading, + rawEventData, + showAlertDetails, + tabType, + timelineId, + ]); if (!expandedEvent?.eventId) { return null; } - return isFlyoutView ? ( + return ( <> - <FlyoutHeader - isHostIsolationPanelOpen={isHostIsolationPanelOpen} - isAlert={isAlert} - isolateAction={isolateAction} - loading={loading} - ruleName={ruleName} - showAlertDetails={showAlertDetails} - timestamp={timestamp} - /> - <FlyoutBody - alertId={alertId} - browserFields={browserFields} - detailsData={detailsData} - event={expandedEvent} - hostName={hostName} - hostRisk={hostRisk} - handleIsolationActionSuccess={handleIsolationActionSuccess} - handleOnEventClosed={handleOnEventClosed} - isAlert={isAlert} - isDraggable={isDraggable} - isolateAction={isolateAction} - isIsolateActionSuccessBannerVisible={isIsolateActionSuccessBannerVisible} - isHostIsolationPanelOpen={isHostIsolationPanelOpen} - loading={loading} - rawEventData={rawEventData} - showAlertDetails={showAlertDetails} - timelineId={timelineId} - isReadOnly={isReadOnly} - /> + {header} + {body} <FlyoutFooter detailsData={detailsData} detailsEcsData={ecsData} @@ -151,41 +248,6 @@ const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({ timelineId={timelineId} /> </> - ) : ( - <> - <ExpandableEventTitle - isAlert={isAlert} - loading={loading} - ruleName={ruleName} - handleOnEventClosed={handleOnEventClosed} - /> - <EuiSpacer size="m" /> - <ExpandableEvent - browserFields={browserFields} - detailsData={detailsData} - event={expandedEvent} - isAlert={isAlert} - isDraggable={isDraggable} - loading={loading} - rawEventData={rawEventData} - timelineId={timelineId} - timelineTabType={tabType} - hostRisk={hostRisk} - handleOnEventClosed={handleOnEventClosed} - /> - <FlyoutFooter - detailsData={detailsData} - detailsEcsData={ecsData} - expandedEvent={expandedEvent} - handleOnEventClosed={handleOnEventClosed} - isHostIsolationPanelOpen={isHostIsolationPanelOpen} - isReadOnly={isReadOnly} - loadingEventDetails={loading} - onAddIsolationStatusClick={showHostIsolationPanel} - refetchFlyoutData={refetchFlyoutData} - timelineId={timelineId} - /> - </> ); }; diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index 8c8629002c93f2..a5b13c083b278f 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -34,13 +34,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'Actions', ], [ - 'Host-nyierkw2gu', + 'Host-dpu1a2r2yi', 'x', 'x', - 'Failure', - 'Windows', - '10.180.151.227, 10.44.18.210', - '7.1.9', + 'Warning', + 'Linux', + '10.2.17.24, 10.56.215.200,10.254.196.130', + '8.5.0', 'x', '', ], @@ -48,10 +48,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'Host-rs9wp4o6l9', 'x', 'x', - 'Warning', - 'Windows', - '10.218.38.118, 10.80.35.162', - '8.0.8', + 'Success', + 'Linux', + '10.138.79.131, 10.170.160.154', + '8.5.0', 'x', '', ], @@ -62,7 +62,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'Warning', 'Linux', '10.87.11.145, 10.117.106.109,10.242.136.97', - '7.13.1', + '8.5.0', 'x', '', ], diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts new file mode 100644 index 00000000000000..d9ff1179f62a9a --- /dev/null +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts @@ -0,0 +1,103 @@ +/* + * 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 { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; +import { TimelineResponse } from '@kbn/security-solution-plugin/common/types'; +import { kibanaPackageJson } from '@kbn/utils'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +/** + * Test suite is meant to cover usages of endpoint functionality or access to endpoint + * functionality from other areas of security solution. + */ +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const endpointService = getService('endpointTestResources'); + const timelineTestService = getService('timeline'); + const detectionsTestService = getService('detections'); + const log = getService('log'); + const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects(['common', 'timeline']); + + describe('App level Endpoint functionality', () => { + let indexedData: IndexedHostsAndAlertsResponse; + let endpointAgentId: string; + + before(async () => { + indexedData = await endpointService.loadEndpointData({ + numHosts: 2, + generatorSeed: `app-level-endpoint-${Math.random()}`, + }); + + endpointAgentId = indexedData.hosts[0].agent.id; + + await endpointService.waitForUnitedEndpoints([endpointAgentId]); + + // Ensure our Endpoint is for v8.0 (or whatever is running in kibana now) + await endpointService.sendEndpointMetadataUpdate(endpointAgentId, { + agent: { version: kibanaPackageJson.version }, + }); + + // start/stop the endpoint rule. This should cause the rule to run immediately + // and avoid us having to wait for the interval (of 5 minutes) + await detectionsTestService.stopStartEndpointRule(); + }); + + after(async () => { + if (indexedData) { + log.info('Cleaning up loaded endpoint data'); + await endpointService.unloadEndpointData(indexedData); + } + }); + + describe('from Timeline', () => { + let timeline: TimelineResponse; + + before(async () => { + timeline = await timelineTestService.createTimelineForEndpointAlerts( + 'endpoint in timeline', + { + endpointAgentId, + } + ); + + // wait for alerts to be available for the Endpoint ID + await detectionsTestService.waitForAlerts( + timelineTestService.getEndpointAlertsKqlQuery(endpointAgentId).esQuery, + // The Alerts rules seems to run every 5 minutes, so we wait here a max + // of 6 minutes to ensure it runs and completes and alerts are available. + 60_000 * 6 + ); + + await pageObjects.timeline.navigateToTimelineList(); + await pageObjects.timeline.openTimelineById( + timeline.data.persistTimeline.timeline.savedObjectId + ); + await pageObjects.timeline.setDateRange('Last 1 year'); + await pageObjects.timeline.waitForEvents(60_000); + }); + + after(async () => { + if (timeline) { + log.info( + `Cleaning up created timeline [${timeline.data.persistTimeline.timeline.title} - ${timeline.data.persistTimeline.timeline.savedObjectId}]` + ); + await timelineTestService.deleteTimeline( + timeline.data.persistTimeline.timeline.savedObjectId + ); + } + }); + + it('should show Isolation action in alert details', async () => { + await pageObjects.timeline.showEventDetails(); + await testSubjects.click('take-action-dropdown-btn'); + await testSubjects.clickWhenNotDisabled('isolate-host-action-item'); + await testSubjects.existOrFail('endpointHostIsolationForm'); + await testSubjects.click('hostIsolateCancelButton'); + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts index 84f90830a3f14f..6aab2457c52788 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts @@ -43,5 +43,6 @@ export default function (providerContext: FtrProviderContext) { loadTestFile(require.resolve('./endpoint_permissions')); loadTestFile(require.resolve('./artifact_entries_list')); loadTestFile(require.resolve('./responder')); + loadTestFile(require.resolve('./endpoint_solution_integrations')); }); } diff --git a/x-pack/test/security_solution_endpoint/services/endpoint.ts b/x-pack/test/security_solution_endpoint/services/endpoint.ts index 50e0b0821ec81d..e29ae10a60df84 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint.ts @@ -5,6 +5,8 @@ * 2.0. */ +/* eslint-disable max-classes-per-file */ + import { errors } from '@elastic/elasticsearch'; import { Client } from '@elastic/elasticsearch'; import { @@ -12,6 +14,8 @@ import { metadataTransformPrefix, METADATA_UNITED_INDEX, METADATA_UNITED_TRANSFORM, + HOST_METADATA_GET_ROUTE, + METADATA_DATASTREAM, } from '@kbn/security-solution-plugin/common/endpoint/constants'; import { deleteIndexedHostsAndAlerts, @@ -24,14 +28,37 @@ import { catchAndWrapError } from '@kbn/security-solution-plugin/server/endpoint import { installOrUpgradeEndpointFleetPackage } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/setup_fleet_for_endpoint'; import { EndpointError } from '@kbn/security-solution-plugin/common/endpoint/errors'; import { STARTED_TRANSFORM_STATES } from '@kbn/security-solution-plugin/common/constants'; +import { DeepPartial } from 'utility-types'; +import { HostInfo, HostMetadata } from '@kbn/security-solution-plugin/common/endpoint/types'; +import { EndpointDocGenerator } from '@kbn/security-solution-plugin/common/endpoint/generate_data'; +import { EndpointMetadataGenerator } from '@kbn/security-solution-plugin/common/endpoint/data_generators/endpoint_metadata_generator'; +import { merge } from 'lodash'; +import { kibanaPackageJson } from '@kbn/utils'; +import seedrandom from 'seedrandom'; import { FtrService } from '../../functional/ftr_provider_context'; +// Document Generator override that uses a custom Endpoint Metadata generator and sets the +// `agent.version` to the current version +const CurrentKibanaVersionDocGenerator = class extends EndpointDocGenerator { + constructor(seedValue: string | seedrandom.prng) { + const MetadataGenerator = class extends EndpointMetadataGenerator { + protected randomVersion(): string { + return kibanaPackageJson.version; + } + }; + + super(seedValue, MetadataGenerator); + } +}; + export class EndpointTestResources extends FtrService { private readonly esClient = this.ctx.getService('es'); private readonly retry = this.ctx.getService('retry'); private readonly kbnClient = this.ctx.getService('kibanaServer'); private readonly transform = this.ctx.getService('transform'); private readonly config = this.ctx.getService('config'); + private readonly supertest = this.ctx.getService('supertest'); + private readonly log = this.ctx.getService('log'); private generateTransformId(endpointPackageVersion?: string): string { return `${metadataTransformPrefix}-${endpointPackageVersion ?? ''}`; @@ -159,7 +186,9 @@ export class EndpointTestResources extends FtrService { 'logs-endpoint.events.process-default', 'logs-endpoint.alerts-default', alertsPerHost, - enableFleetIntegration + enableFleetIntegration, + undefined, + CurrentKibanaVersionDocGenerator ); if (waitUntilTransformed) { @@ -291,4 +320,67 @@ export class EndpointTestResources extends FtrService { > { return installOrUpgradeEndpointFleetPackage(this.kbnClient); } + + /** + * Fetch (GET) the details of an endpoint + * @param endpointAgentId + */ + async fetchEndpointMetadata(endpointAgentId: string): Promise<HostInfo> { + const metadata = this.supertest + .get(HOST_METADATA_GET_ROUTE.replace('{id}', endpointAgentId)) + .set('kbn-xsrf', 'true') + .send() + .expect(200) + .then((response) => response.body as HostInfo); + + return metadata; + } + + /** + * Sends an updated metadata document for a given endpoint to the datastream and waits for the + * update to show up on the Metadata API (after transform runs) + */ + async sendEndpointMetadataUpdate( + endpointAgentId: string, + updates: DeepPartial<HostMetadata> = {} + ): Promise<HostInfo> { + const currentMetadata = await this.fetchEndpointMetadata(endpointAgentId); + const generatedMetadataDoc = new EndpointDocGenerator().generateHostMetadata(); + + const updatedMetadataDoc = merge( + { ...currentMetadata.metadata }, + // Grab the updated `event` and timestamp from the generator data + { + event: generatedMetadataDoc.event, + '@timestamp': generatedMetadataDoc['@timestamp'], + }, + updates + ); + + await this.esClient.index({ + index: METADATA_DATASTREAM, + body: updatedMetadataDoc, + op_type: 'create', + }); + + let response: HostInfo | undefined; + + // Wait for the update to show up on Metadata API (after transform runs) + await this.retry.waitFor( + `Waiting for update to endpoint id [${endpointAgentId}] to be processed by transform`, + async () => { + response = await this.fetchEndpointMetadata(endpointAgentId); + + return response.metadata.event.id === updatedMetadataDoc.event.id; + } + ); + + if (!response) { + throw new Error(`Response object not set. Issue fetching endpoint metadata`); + } + + this.log.info(`Endpoint metadata doc update done: \n${JSON.stringify(response)}`); + + return response; + } } diff --git a/x-pack/test/security_solution_ftr/services/timeline/index.ts b/x-pack/test/security_solution_ftr/services/timeline/index.ts index 5c6e96b4ce0be8..38e7d2a667cd29 100644 --- a/x-pack/test/security_solution_ftr/services/timeline/index.ts +++ b/x-pack/test/security_solution_ftr/services/timeline/index.ts @@ -11,6 +11,7 @@ import { TIMELINE_DRAFT_URL, TIMELINE_URL } from '@kbn/security-solution-plugin/ import { TimelineResponse } from '@kbn/security-solution-plugin/common/types'; import { TimelineInput } from '@kbn/security-solution-plugin/common/search_strategy'; import moment from 'moment'; +import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { FtrService } from '../../../functional/ftr_provider_context'; export class TimelineTestService extends FtrService { @@ -67,10 +68,9 @@ export class TimelineTestService extends FtrService { this.log.info(JSON.stringify(createdTimeline)); }); - const { savedObjectId: timelineId, version, ...timelineDoc } = createdTimeline; + const { savedObjectId: timelineId, version } = createdTimeline; const timelineUpdate: TimelineInput = { - ...(timelineDoc as TimelineInput), title, // Set date range to the last 1 year dateRange: { @@ -109,9 +109,6 @@ export class TimelineTestService extends FtrService { version: string ): Promise<TimelineResponse> { return await this.supertest - // DEV NOTE/FYI: - // Although this API is a `patch`, it does not seem that it actually does a patch, - // so `updates` should always be the full timeline record .patch(TIMELINE_URL) .set('kbn-xsrf', 'true') .send({ @@ -134,4 +131,66 @@ export class TimelineTestService extends FtrService { .then(this.getHttpResponseFailureHandler()) .then((response) => response.body as TimelineResponse); } + + /** + * Get the KQL query that will filter the content of a timeline to display Endpoint alerts + * @param endpointAgentId + */ + getEndpointAlertsKqlQuery(endpointAgentId?: string): { + expression: string; + esQuery: ReturnType<typeof toElasticsearchQuery>; + } { + const expression = [ + 'agent.type: "endpoint"', + 'kibana.alert.rule.uuid : *', + ...(endpointAgentId ? [`agent.id: "${endpointAgentId}"`] : []), + ].join(' AND '); + + const esQuery = toElasticsearchQuery(fromKueryExpression(expression)); + + return { + expression, + esQuery, + }; + } + + /** + * Crates a new Timeline and sets its `kqlQuery` so that Endpoint Alerts are displayed. + * Can be limited to an endpoint by providing its `agent.id` + * + * @param title + * @param endpointAgentId + */ + async createTimelineForEndpointAlerts( + title: string, + { + endpointAgentId, + }: Partial<{ + /** If defined, then only alerts from the specific `agent.id` will be displayed */ + endpointAgentId: string; + }> + ): Promise<TimelineResponse> { + const newTimeline = await this.createTimeline(title); + + const { expression, esQuery } = this.getEndpointAlertsKqlQuery(endpointAgentId); + + const updatedTimeline = await this.updateTimeline( + newTimeline.data.persistTimeline.timeline.savedObjectId, + { + title, + kqlQuery: { + filterQuery: { + kuery: { + kind: 'kuery', + expression, + }, + serializedQuery: JSON.stringify(esQuery), + }, + }, + }, + newTimeline.data.persistTimeline.timeline.version + ); + + return updatedTimeline; + } } From fd424e627aac6457faa92a8b32d4dbb0de424f13 Mon Sep 17 00:00:00 2001 From: Shahzad <shahzad.muhammad@elastic.co> Date: Mon, 12 Sep 2022 15:57:46 +0200 Subject: [PATCH 065/144] [Synthetics] Fix monitor summary page layout (#140492) --- .../monitor_summary/monitor_summary_title.tsx | 16 +++++++++++++--- .../synthetics/public/apps/synthetics/routes.tsx | 12 +++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/monitor_summary_title.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/monitor_summary_title.tsx index d8c8e4394f3a56..9e295496dd77c0 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/monitor_summary_title.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_summary/monitor_summary_title.tsx @@ -10,6 +10,7 @@ import { useParams } from 'react-router-dom'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { MonitorSummaryLastRunInfo } from './last_run_info'; import { getMonitorStatusAction, selectMonitorStatus } from '../../state'; +import { RunTestManually } from './run_test_manually'; export const MonitorSummaryTitle = () => { const dispatch = useDispatch(); @@ -23,9 +24,18 @@ export const MonitorSummaryTitle = () => { }, [dispatch, monitorId]); return ( - <EuiFlexGroup direction="column" gutterSize="xs"> - <EuiFlexItem>{data?.monitor.name}</EuiFlexItem> - <EuiFlexItem grow={false}>{data && <MonitorSummaryLastRunInfo ping={data} />}</EuiFlexItem> + <EuiFlexGroup> + <EuiFlexItem> + <EuiFlexGroup direction="column" gutterSize="xs"> + <EuiFlexItem>{data?.monitor.name}</EuiFlexItem> + <EuiFlexItem grow={false}> + {data && <MonitorSummaryLastRunInfo ping={data} />} + </EuiFlexItem> + </EuiFlexGroup> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <RunTestManually /> + </EuiFlexItem> </EuiFlexGroup> ); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx index 12783d39e27112..8da37518fbede2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx @@ -17,7 +17,6 @@ import { useInspectorContext } from '@kbn/observability-plugin/public'; import type { LazyObservabilityPageTemplateProps } from '@kbn/observability-plugin/public'; import { MonitorAddPage } from './components/monitor_add_edit/monitor_add_page'; import { MonitorEditPage } from './components/monitor_add_edit/monitor_edit_page'; -import { RunTestManually } from './components/monitor_summary/run_test_manually'; import { MonitorSummaryHeaderContent } from './components/monitor_summary/monitor_summary_header_content'; import { MonitorSummaryTitle } from './components/monitor_summary/monitor_summary_title'; import { MonitorSummaryPage } from './components/monitor_summary/monitor_summary'; @@ -79,22 +78,17 @@ const getRoutes = ( }, }, { - title: i18n.translate('xpack.synthetics.gettingStartedRoute.title', { - defaultMessage: 'Synthetics Getting Started | {baseTitle}', + title: i18n.translate('xpack.synthetics.monitorSummaryRoute.title', { + defaultMessage: 'Monitor summary | {baseTitle}', values: { baseTitle }, }), path: MONITOR_ROUTE, component: () => <MonitorSummaryPage />, dataTestSubj: 'syntheticsGettingStartedPage', - pageSectionProps: { - alignment: 'center', - paddingSize: 'none', - }, pageHeader: { - paddingSize: 'none', children: <MonitorSummaryHeaderContent />, pageTitle: <MonitorSummaryTitle />, - rightSideItems: [<RunTestManually />], + // rightSideItems: [<RunTestManually />], }, }, { From cc5ff75733d038159e68f4a3201dce68994d6ad0 Mon Sep 17 00:00:00 2001 From: Kyle Pollich <kyle.pollich@elastic.co> Date: Mon, 12 Sep 2022 10:01:48 -0400 Subject: [PATCH 066/144] [Fleet] Add toggle for experimental synthetic `_source` support in Fleet data streams (#140132) * First pass at synthetic source support in Fleet * Fix some type failures + clean up naming * Fix more types * Avoid needless PUTs to component templates when opt-in is unchanged * Honor experimental data stream settings during dry-run/upgrade workflow * Remove docs link for now * Fix various bugs in logic/lookups + add tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fleet_integration/fleet_integration.ts | 3 +- .../plugins/fleet/common/types/models/epm.ts | 13 + .../common/types/models/package_policy.ts | 3 + .../components/package_policy_input_panel.tsx | 3 + .../package_policy_input_stream.tsx | 353 +++++++++++------- .../steps/step_configure_package.tsx | 1 + .../fleet/server/saved_objects/index.ts | 12 + .../server/services/epm/packages/update.ts | 20 + .../experimental_datastream_features.test.ts | 212 +++++++++++ .../experimental_datastream_features.ts | 88 +++++ .../server/services/package_policies/index.ts | 1 + .../fleet/server/services/package_policy.ts | 104 +++++- .../server/types/models/package_policy.ts | 18 + 13 files changed, 681 insertions(+), 150 deletions(-) create mode 100644 x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts create mode 100644 x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index 6c5701a6593ee2..39db06473c9a96 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -17,6 +17,7 @@ import { DeletePackagePoliciesResponse, PackagePolicyInput, } from '@kbn/fleet-plugin/common'; +import { DeepReadonly } from 'utility-types'; import { createCspRuleSearchFilterByPackagePolicy } from '../../common/utils/helpers'; import { CLOUDBEAT_VANILLA, @@ -85,7 +86,7 @@ export const onPackagePolicyPostCreateCallback = async ( * Callback to handle deletion of PackagePolicies in Fleet */ export const removeCspRulesInstancesCallback = async ( - deletedPackagePolicy: DeletePackagePoliciesResponse[number], + deletedPackagePolicy: DeepReadonly<DeletePackagePoliciesResponse[number]>, soClient: ISavedObjectsRepository, logger: Logger ): Promise<void> => { diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 8c8e6288d474ed..519222b4e3c101 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -417,6 +417,14 @@ export type PackageInfo = | Installable<Merge<RegistryPackage, EpmPackageAdditions>> | Installable<Merge<ArchivePackage, EpmPackageAdditions>>; +// TODO - Expand this with other experimental indexing types +export type ExperimentalIndexingFeature = 'synthetic_source'; + +export interface ExperimentalDataStreamFeature { + data_stream: string; + features: Record<ExperimentalIndexingFeature, boolean>; +} + export interface Installation extends SavedObjectAttributes { installed_kibana: KibanaAssetReference[]; installed_es: EsAssetReference[]; @@ -433,6 +441,11 @@ export interface Installation extends SavedObjectAttributes { install_format_schema_version?: string; verification_status: PackageVerificationStatus; verification_key_id?: string | null; + // TypeScript doesn't like using the `ExperimentalDataStreamFeature` type defined above here + experimental_data_stream_features?: Array<{ + data_stream: string; + features: Record<ExperimentalIndexingFeature, boolean>; + }>; } export interface PackageUsageStats { diff --git a/x-pack/plugins/fleet/common/types/models/package_policy.ts b/x-pack/plugins/fleet/common/types/models/package_policy.ts index ec6b04ae64fc8e..4673fefbd9536f 100644 --- a/x-pack/plugins/fleet/common/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/package_policy.ts @@ -5,10 +5,13 @@ * 2.0. */ +import type { ExperimentalDataStreamFeature } from './epm'; + export interface PackagePolicyPackage { name: string; title: string; version: string; + experimental_data_stream_features?: ExperimentalDataStreamFeature[]; } export interface PackagePolicyConfigRecordEntry { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx index b34ce952977619..1d0cda70edea4e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_panel.tsx @@ -75,6 +75,7 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ packagePolicy: NewPackagePolicy; packageInputStreams: Array<RegistryStream & { data_stream: { dataset: string; type: string } }>; packagePolicyInput: NewPackagePolicyInput; + updatePackagePolicy: (updatedPackagePolicy: Partial<NewPackagePolicy>) => void; updatePackagePolicyInput: (updatedInput: Partial<NewPackagePolicyInput>) => void; inputValidationResults: PackagePolicyInputValidationResults; forceShowErrors?: boolean; @@ -85,6 +86,7 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ packageInputStreams, packagePolicyInput, packagePolicy, + updatePackagePolicy, updatePackagePolicyInput, inputValidationResults, forceShowErrors, @@ -236,6 +238,7 @@ export const PackagePolicyInputPanel: React.FunctionComponent<{ packagePolicy={packagePolicy} packageInputStream={packageInputStream} packagePolicyInputStream={packagePolicyInputStream!} + updatePackagePolicy={updatePackagePolicy} updatePackagePolicyInputStream={( updatedStream: Partial<PackagePolicyInputStream> ) => { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx index 1662f6d0c72140..166078eb01dd24 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx @@ -17,9 +17,12 @@ import { EuiText, EuiSpacer, EuiButtonEmpty, + EuiTitle, } from '@elastic/eui'; import { useRouteMatch } from 'react-router-dom'; +import { getRegistryDataStreamAssetBaseName } from '../../../../../../../../../common/services'; + import type { NewPackagePolicy, NewPackagePolicyInputStream, @@ -48,6 +51,7 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ packageInputStream: RegistryStream & { data_stream: { dataset: string; type: string } }; packageInfo: PackageInfo; packagePolicyInputStream: NewPackagePolicyInputStream; + updatePackagePolicy: (updatedPackagePolicy: Partial<NewPackagePolicy>) => void; updatePackagePolicyInputStream: (updatedStream: Partial<NewPackagePolicyInputStream>) => void; inputStreamValidationResults: PackagePolicyConfigValidationResults; forceShowErrors?: boolean; @@ -57,6 +61,7 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ packageInputStream, packageInfo, packagePolicyInputStream, + updatePackagePolicy, updatePackagePolicyInputStream, inputStreamValidationResults, forceShowErrors, @@ -111,150 +116,226 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ ); return ( - <EuiFlexGrid columns={2} id={isDefaultDatstream ? 'test123' : 'asas'}> - <ScrollAnchor ref={containerRef} /> - <EuiFlexItem> - <EuiFlexGroup gutterSize="none" alignItems="flexStart"> - <EuiFlexItem grow={1} /> - <EuiFlexItem grow={5}> - <EuiSwitch - label={packageInputStream.title} - disabled={packagePolicyInputStream.keep_enabled} - checked={packagePolicyInputStream.enabled} - onChange={(e) => { - const enabled = e.target.checked; - updatePackagePolicyInputStream({ - enabled, - }); - }} - /> - {packageInputStream.description ? ( - <Fragment> - <EuiSpacer size="s" /> - <EuiText size="s" color="subdued"> - <ReactMarkdown>{packageInputStream.description}</ReactMarkdown> - </EuiText> - </Fragment> - ) : null} - </EuiFlexItem> - </EuiFlexGroup> - </EuiFlexItem> - <FlexItemWithMaxWidth> - <EuiFlexGroup direction="column" gutterSize="m"> - {requiredVars.map((varDef) => { - if (!packagePolicyInputStream?.vars) return null; - const { name: varName, type: varType } = varDef; - const varConfigEntry = packagePolicyInputStream.vars?.[varName]; - const value = varConfigEntry?.value; - const frozen = varConfigEntry?.frozen ?? false; + <> + <EuiFlexGrid columns={2} id={isDefaultDatstream ? 'test123' : 'asas'}> + <ScrollAnchor ref={containerRef} /> + <EuiFlexItem> + <EuiFlexGroup gutterSize="none" alignItems="flexStart"> + <EuiFlexItem grow={1} /> + <EuiFlexItem grow={5}> + <EuiSwitch + label={packageInputStream.title} + disabled={packagePolicyInputStream.keep_enabled} + checked={packagePolicyInputStream.enabled} + onChange={(e) => { + const enabled = e.target.checked; + updatePackagePolicyInputStream({ + enabled, + }); + }} + /> + {packageInputStream.description ? ( + <Fragment> + <EuiSpacer size="s" /> + <EuiText size="s" color="subdued"> + <ReactMarkdown>{packageInputStream.description}</ReactMarkdown> + </EuiText> + </Fragment> + ) : null} + </EuiFlexItem> + </EuiFlexGroup> + </EuiFlexItem> + <FlexItemWithMaxWidth> + <EuiFlexGroup direction="column" gutterSize="m"> + {requiredVars.map((varDef) => { + if (!packagePolicyInputStream?.vars) return null; + const { name: varName, type: varType } = varDef; + const varConfigEntry = packagePolicyInputStream.vars?.[varName]; + const value = varConfigEntry?.value; + const frozen = varConfigEntry?.frozen ?? false; - return ( - <EuiFlexItem key={varName}> - <PackagePolicyInputVarField - varDef={varDef} - value={value} - frozen={frozen} - onChange={(newValue: any) => { - updatePackagePolicyInputStream({ - vars: { - ...packagePolicyInputStream.vars, - [varName]: { - type: varType, - value: newValue, + return ( + <EuiFlexItem key={varName}> + <PackagePolicyInputVarField + varDef={varDef} + value={value} + frozen={frozen} + onChange={(newValue: any) => { + updatePackagePolicyInputStream({ + vars: { + ...packagePolicyInputStream.vars, + [varName]: { + type: varType, + value: newValue, + }, }, - }, - }); - }} - errors={inputStreamValidationResults?.vars![varName]} - forceShowErrors={forceShowErrors} - /> - </EuiFlexItem> - ); - })} - {/* Advanced section */} - {(isPackagePolicyEdit || !!advancedVars.length) && ( - <Fragment> - <EuiFlexItem> - <EuiFlexGroup justifyContent="spaceBetween" alignItems="center"> - <EuiFlexItem grow={false}> - <EuiButtonEmpty - size="xs" - iconType={isShowingAdvanced ? 'arrowDown' : 'arrowRight'} - onClick={() => setIsShowingAdvanced(!isShowingAdvanced)} - flush="left" - > - <FormattedMessage - id="xpack.fleet.createPackagePolicy.stepConfigure.toggleAdvancedOptionsButtonText" - defaultMessage="Advanced options" - /> - </EuiButtonEmpty> - </EuiFlexItem> - {!isShowingAdvanced && hasErrors && advancedVarsWithErrorsCount ? ( + }); + }} + errors={inputStreamValidationResults?.vars![varName]} + forceShowErrors={forceShowErrors} + /> + </EuiFlexItem> + ); + })} + {/* Advanced section */} + {(isPackagePolicyEdit || !!advancedVars.length) && ( + <Fragment> + <EuiFlexItem> + <EuiFlexGroup justifyContent="spaceBetween" alignItems="center"> <EuiFlexItem grow={false}> - <EuiText color="danger" size="s"> + <EuiButtonEmpty + size="xs" + iconType={isShowingAdvanced ? 'arrowDown' : 'arrowRight'} + onClick={() => setIsShowingAdvanced(!isShowingAdvanced)} + flush="left" + > <FormattedMessage - id="xpack.fleet.createPackagePolicy.stepConfigure.errorCountText" - defaultMessage="{count, plural, one {# error} other {# errors}}" - values={{ count: advancedVarsWithErrorsCount }} + id="xpack.fleet.createPackagePolicy.stepConfigure.toggleAdvancedOptionsButtonText" + defaultMessage="Advanced options" /> - </EuiText> + </EuiButtonEmpty> </EuiFlexItem> - ) : null} - </EuiFlexGroup> - </EuiFlexItem> - {isShowingAdvanced ? ( - <> - {advancedVars.map((varDef) => { - if (!packagePolicyInputStream.vars) return null; - const { name: varName, type: varType } = varDef; - const value = packagePolicyInputStream.vars?.[varName]?.value; + {!isShowingAdvanced && hasErrors && advancedVarsWithErrorsCount ? ( + <EuiFlexItem grow={false}> + <EuiText color="danger" size="s"> + <FormattedMessage + id="xpack.fleet.createPackagePolicy.stepConfigure.errorCountText" + defaultMessage="{count, plural, one {# error} other {# errors}}" + values={{ count: advancedVarsWithErrorsCount }} + /> + </EuiText> + </EuiFlexItem> + ) : null} + </EuiFlexGroup> + </EuiFlexItem> + {isShowingAdvanced ? ( + <> + {advancedVars.map((varDef) => { + if (!packagePolicyInputStream.vars) return null; + const { name: varName, type: varType } = varDef; + const value = packagePolicyInputStream.vars?.[varName]?.value; - return ( - <EuiFlexItem key={varName}> - <PackagePolicyInputVarField - varDef={varDef} - value={value} - onChange={(newValue: any) => { - updatePackagePolicyInputStream({ - vars: { - ...packagePolicyInputStream.vars, - [varName]: { - type: varType, - value: newValue, + return ( + <EuiFlexItem key={varName}> + <PackagePolicyInputVarField + varDef={varDef} + value={value} + onChange={(newValue: any) => { + updatePackagePolicyInputStream({ + vars: { + ...packagePolicyInputStream.vars, + [varName]: { + type: varType, + value: newValue, + }, }, - }, - }); - }} - errors={inputStreamValidationResults?.vars![varName]} - forceShowErrors={forceShowErrors} - /> - </EuiFlexItem> - ); - })} - {/* Only show datastream pipelines and mappings on edit */} - {isPackagePolicyEdit && ( - <> - <EuiFlexItem> - <PackagePolicyEditorDatastreamPipelines - packageInputStream={packagePolicyInputStream} - packageInfo={packageInfo} - /> - </EuiFlexItem> - <EuiFlexItem> - <PackagePolicyEditorDatastreamMappings - packageInputStream={packagePolicyInputStream} - packageInfo={packageInfo} - /> - </EuiFlexItem> - </> - )} - </> - ) : null} - </Fragment> - )} - </EuiFlexGroup> - </FlexItemWithMaxWidth> - </EuiFlexGrid> + }); + }} + errors={inputStreamValidationResults?.vars![varName]} + forceShowErrors={forceShowErrors} + /> + </EuiFlexItem> + ); + })} + {/* Only show datastream pipelines and mappings on edit */} + {isPackagePolicyEdit && ( + <> + <EuiFlexItem> + <PackagePolicyEditorDatastreamPipelines + packageInputStream={packagePolicyInputStream} + packageInfo={packageInfo} + /> + </EuiFlexItem> + <EuiFlexItem> + <PackagePolicyEditorDatastreamMappings + packageInputStream={packagePolicyInputStream} + packageInfo={packageInfo} + /> + </EuiFlexItem> + </> + )} + {/* Experimental index/datastream settings e.g. synthetic source */} + <EuiFlexItem> + <EuiFlexGroup direction="column" gutterSize="xs"> + <EuiFlexItem grow={false}> + <EuiTitle size="xxxs"> + <h5> + <FormattedMessage + id="xpack.fleet.packagePolicyEditor.experimentalSettings.title" + defaultMessage="Indexing settings (experimental)" + /> + </h5> + </EuiTitle> + </EuiFlexItem> + <EuiFlexItem> + <EuiText color="subdued" size="xs"> + <FormattedMessage + id="xpack.fleet.createPackagePolicy.stepConfigure.experimentalFeaturesDescription" + defaultMessage="Select data streams to configure indexing options. This is an {experimentalFeature} and may have effects on other properties." + values={{ + experimentalFeature: ( + <strong> + <FormattedMessage + id="xpack.fleet.createPackagePolicy.experimentalFeatureText" + defaultMessage="experimental feature" + /> + </strong> + ), + }} + /> + </EuiText> + </EuiFlexItem> + <EuiSpacer size="s" /> + <EuiFlexItem> + <EuiSwitch + checked={ + packagePolicy.package?.experimental_data_stream_features?.some( + ({ data_stream: dataStream, features }) => + dataStream === + getRegistryDataStreamAssetBaseName( + packagePolicyInputStream.data_stream + ) && features.synthetic_source + ) ?? false + } + label={ + <FormattedMessage + id="xpack.fleet.createPackagePolicy.experimentalFeatures.syntheticSourceLabel" + defaultMessage="Synthetic source" + /> + } + onChange={(e) => { + if (!packagePolicy.package) { + return; + } + + updatePackagePolicy({ + package: { + ...packagePolicy.package, + experimental_data_stream_features: [ + { + data_stream: getRegistryDataStreamAssetBaseName( + packagePolicyInputStream.data_stream + ), + features: { + synthetic_source: e.target.checked, + }, + }, + ], + }, + }); + }} + /> + </EuiFlexItem> + </EuiFlexGroup> + </EuiFlexItem> + </> + ) : null} + </Fragment> + )} + </EuiFlexGroup> + </FlexItemWithMaxWidth> + </EuiFlexGrid> + </> ); } ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx index 57b5376c9fbb7e..541f54b792c7bb 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_configure_package.tsx @@ -76,6 +76,7 @@ export const StepConfigurePackagePolicy: React.FunctionComponent<{ packagePolicy={packagePolicy} packageInputStreams={packageInputStreams} packagePolicyInput={packagePolicyInput} + updatePackagePolicy={updatePackagePolicy} updatePackagePolicyInput={(updatedInput: Partial<NewPackagePolicyInput>) => { const indexOfUpdatedInput = packagePolicy.inputs.findIndex( (input) => diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index bd031cf9b02741..55d38b00dec3de 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -271,6 +271,18 @@ const getSavedObjectTypes = ( install_status: { type: 'keyword' }, install_source: { type: 'keyword' }, install_format_schema_version: { type: 'version' }, + experimental_data_stream_features: { + type: 'nested', + properties: { + data_stream: { type: 'keyword' }, + features: { + type: 'nested', + properties: { + synthetic_source: { type: 'boolean' }, + }, + }, + }, + }, }, }, migrations: { diff --git a/x-pack/plugins/fleet/server/services/epm/packages/update.ts b/x-pack/plugins/fleet/server/services/epm/packages/update.ts index 4ab47954f51ca6..224c9332fad62a 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/update.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/update.ts @@ -8,6 +8,8 @@ import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; +import type { ExperimentalIndexingFeature } from '../../../../common/types'; + import { PACKAGES_SAVED_OBJECT_TYPE } from '../../../constants'; import type { Installation, UpdatePackageRequestSchema } from '../../../types'; import { IngestManagerError } from '../../../errors'; @@ -40,3 +42,21 @@ export async function updatePackage( return packageInfo; } + +export async function updateDatastreamExperimentalFeatures( + savedObjectsClient: SavedObjectsClientContract, + pkgName: string, + dataStreamFeatureMapping: Array<{ + data_stream: string; + features: Record<ExperimentalIndexingFeature, boolean>; + }> +) { + await savedObjectsClient.update<Installation>( + PACKAGES_SAVED_OBJECT_TYPE, + pkgName, + { + experimental_data_stream_features: dataStreamFeatureMapping, + }, + { refresh: 'wait_for' } + ); +} diff --git a/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts new file mode 100644 index 00000000000000..8c7afa5d30fed9 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.test.ts @@ -0,0 +1,212 @@ +/* + * 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 { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; + +import type { NewPackagePolicy, PackagePolicy } from '../../types'; + +import { handleExperimentalDatastreamFeatureOptIn } from './experimental_datastream_features'; + +function getNewTestPackagePolicy({ + isSyntheticSourceEnabled, +}: { + isSyntheticSourceEnabled: boolean; +}): NewPackagePolicy { + const packagePolicy: NewPackagePolicy = { + name: 'Test policy', + policy_id: 'agent-policy', + description: 'Test policy description', + namespace: 'default', + enabled: true, + inputs: [], + package: { + name: 'test', + title: 'Test', + version: '0.0.1', + experimental_data_stream_features: [ + { + data_stream: 'metrics-test.test', + features: { + synthetic_source: isSyntheticSourceEnabled, + }, + }, + ], + }, + }; + + return packagePolicy; +} + +function getExistingTestPackagePolicy({ + isSyntheticSourceEnabled, +}: { + isSyntheticSourceEnabled: boolean; +}): PackagePolicy { + const packagePolicy: PackagePolicy = { + id: 'test-policy', + name: 'Test policy', + policy_id: 'agent-policy', + description: 'Test policy description', + namespace: 'default', + enabled: true, + inputs: [], + package: { + name: 'test', + title: 'Test', + version: '0.0.1', + experimental_data_stream_features: [ + { + data_stream: 'metrics-test.test', + features: { + synthetic_source: isSyntheticSourceEnabled, + }, + }, + ], + }, + revision: 1, + created_by: 'system', + created_at: '2022-01-01T00:00:00.000Z', + updated_by: 'system', + updated_at: '2022-01-01T00:00:00.000Z', + }; + + return packagePolicy; +} + +describe('experimental_datastream_features', () => { + beforeEach(() => { + soClient.get.mockClear(); + esClient.cluster.getComponentTemplate.mockClear(); + esClient.cluster.putComponentTemplate.mockClear(); + }); + + const soClient = savedObjectsClientMock.create(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + + describe('when package policy does not exist (create)', () => { + it('updates component template', async () => { + const packagePolicy = getNewTestPackagePolicy({ isSyntheticSourceEnabled: true }); + + soClient.get.mockResolvedValueOnce({ + attributes: { + experimental_data_stream_features: [ + { data_stream: 'metrics-test.test', features: { synthetic_source: false } }, + ], + }, + id: 'mocked', + type: 'mocked', + references: [], + }); + + esClient.cluster.getComponentTemplate.mockResolvedValueOnce({ + component_templates: [ + { + name: 'metrics-test.test@package', + component_template: { + template: { + settings: {}, + mappings: { + _source: { + // @ts-expect-error + mode: 'stored', + }, + }, + }, + }, + }, + ], + }); + + await handleExperimentalDatastreamFeatureOptIn({ soClient, esClient, packagePolicy }); + + expect(esClient.cluster.getComponentTemplate).toHaveBeenCalled(); + expect(esClient.cluster.putComponentTemplate).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + template: expect.objectContaining({ + mappings: expect.objectContaining({ _source: { mode: 'synthetic' } }), + }), + }), + }) + ); + }); + }); + + describe('when package policy exists (update)', () => { + describe('when opt in status in unchanged', () => { + it('does not update component template', async () => { + const packagePolicy = getExistingTestPackagePolicy({ isSyntheticSourceEnabled: true }); + + soClient.get.mockResolvedValueOnce({ + attributes: { + experimental_data_stream_features: [ + { data_stream: 'metrics-test.test', features: { synthetic_source: true } }, + ], + }, + id: 'mocked', + type: 'mocked', + references: [], + }); + + await handleExperimentalDatastreamFeatureOptIn({ soClient, esClient, packagePolicy }); + + expect(esClient.cluster.getComponentTemplate).not.toHaveBeenCalled(); + expect(esClient.cluster.putComponentTemplate).not.toHaveBeenCalled(); + }); + }); + + describe('when opt in status is changed', () => { + it('updates component template', async () => { + const packagePolicy = getExistingTestPackagePolicy({ isSyntheticSourceEnabled: true }); + + soClient.get.mockResolvedValueOnce({ + attributes: { + experimental_data_stream_features: [ + { data_stream: 'metrics-test.test', features: { synthetic_source: false } }, + ], + }, + id: 'mocked', + type: 'mocked', + references: [], + }); + + esClient.cluster.getComponentTemplate.mockResolvedValueOnce({ + component_templates: [ + { + name: 'metrics-test.test@package', + component_template: { + template: { + settings: {}, + mappings: { + _source: { + // @ts-expect-error + mode: 'stored', + }, + }, + }, + }, + }, + ], + }); + + await handleExperimentalDatastreamFeatureOptIn({ soClient, esClient, packagePolicy }); + + expect(esClient.cluster.getComponentTemplate).toHaveBeenCalled(); + expect(esClient.cluster.putComponentTemplate).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + template: expect.objectContaining({ + mappings: expect.objectContaining({ _source: { mode: 'synthetic' } }), + }), + }), + }) + ); + }); + }); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts new file mode 100644 index 00000000000000..2b8b05aed89c37 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/package_policies/experimental_datastream_features.ts @@ -0,0 +1,88 @@ +/* + * 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 type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; + +import type { NewPackagePolicy, PackagePolicy } from '../../types'; +import { getInstallation } from '../epm/packages'; +import { updateDatastreamExperimentalFeatures } from '../epm/packages/update'; + +export async function handleExperimentalDatastreamFeatureOptIn({ + soClient, + esClient, + packagePolicy, +}: { + soClient: SavedObjectsClientContract; + esClient: ElasticsearchClient; + packagePolicy: PackagePolicy | NewPackagePolicy; +}) { + if (!packagePolicy.package?.experimental_data_stream_features) { + return; + } + + // If we're performing an update, we want to check if we actually need to perform + // an update to the component templates for the package. So we fetch the saved object + // for the package policy here to compare later. + let installation; + + if (packagePolicy.package) { + installation = await getInstallation({ + savedObjectsClient: soClient, + pkgName: packagePolicy.package.name, + }); + } + + for (const featureMapEntry of packagePolicy.package.experimental_data_stream_features) { + const existingOptIn = installation?.experimental_data_stream_features?.find( + (optIn) => optIn.data_stream === featureMapEntry.data_stream + ); + + const isOptInChanged = + existingOptIn?.features.synthetic_source !== featureMapEntry.features.synthetic_source; + + // If the feature opt-in status in unchanged, we don't need to update any component templates + if (!isOptInChanged) { + continue; + } + + const componentTemplateName = `${featureMapEntry.data_stream}@package`; + const componentTemplateRes = await esClient.cluster.getComponentTemplate({ + name: componentTemplateName, + }); + + const componentTemplate = componentTemplateRes.component_templates[0].component_template; + + const body = { + template: { + ...componentTemplate.template, + mappings: { + ...componentTemplate.template.mappings, + _source: { + mode: featureMapEntry.features.synthetic_source ? 'synthetic' : 'stored', + }, + }, + }, + }; + + await esClient.cluster.putComponentTemplate({ + name: componentTemplateName, + // @ts-expect-error - TODO: Remove when ES client typings include support for synthetic source + body, + }); + } + + // Update the installation object to persist the experimental feature map + await updateDatastreamExperimentalFeatures( + soClient, + packagePolicy.package.name, + packagePolicy.package.experimental_data_stream_features + ); + + // Delete the experimental features map from the package policy so it doesn't get persisted + delete packagePolicy.package.experimental_data_stream_features; +} diff --git a/x-pack/plugins/fleet/server/services/package_policies/index.ts b/x-pack/plugins/fleet/server/services/package_policies/index.ts index e79ef475025049..d0d4fa4aae8250 100644 --- a/x-pack/plugins/fleet/server/services/package_policies/index.ts +++ b/x-pack/plugins/fleet/server/services/package_policies/index.ts @@ -5,4 +5,5 @@ * 2.0. */ +export * from './experimental_datastream_features'; export * from './package_policy_name_helper'; diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 3d481db8d63dc0..134abb86b68931 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -32,7 +32,12 @@ import { validatePackagePolicy, validationHasErrors, } from '../../common/services'; -import { SO_SEARCH_LIMIT, FLEET_APM_PACKAGE, outputType } from '../../common/constants'; +import { + SO_SEARCH_LIMIT, + FLEET_APM_PACKAGE, + outputType, + PACKAGES_SAVED_OBJECT_TYPE, +} from '../../common/constants'; import type { DeletePackagePoliciesResponse, UpgradePackagePolicyResponse, @@ -46,6 +51,8 @@ import type { UpgradePackagePolicyDryRunResponseItem, RegistryDataStream, PackagePolicyPackage, + Installation, + ExperimentalDataStreamFeature, } from '../../common/types'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../constants'; import { @@ -80,6 +87,8 @@ import { appContextService } from '.'; import { removeOldAssets } from './epm/packages/cleanup'; import type { PackageUpdateEvent, UpdateEventType } from './upgrade_sender'; import { sendTelemetryEvents } from './upgrade_sender'; +import { handleExperimentalDatastreamFeatureOptIn } from './package_policies'; +import { updateDatastreamExperimentalFeatures } from './epm/packages/update'; export type InputsOverride = Partial<NewPackagePolicyInput> & { vars?: Array<NewPackagePolicyInput['vars'] & { name: string }>; @@ -159,6 +168,9 @@ class PackagePolicyService implements PackagePolicyServiceInterface { }); } + // Handle component template/mappings updates for experimental features, e.g. synthetic source + await handleExperimentalDatastreamFeatureOptIn({ soClient, esClient, packagePolicy }); + const pkgInfo = options?.packageInfo ?? (await getPackageInfo({ @@ -279,11 +291,31 @@ class PackagePolicyService implements PackagePolicyServiceInterface { throw new Error(packagePolicySO.error.message); } - return { + let experimentalFeatures: ExperimentalDataStreamFeature[] | undefined; + + if (packagePolicySO.attributes.package?.name) { + const installation = await soClient.get<Installation>( + PACKAGES_SAVED_OBJECT_TYPE, + packagePolicySO.attributes.package?.name + ); + + if (installation && !installation.error) { + experimentalFeatures = installation.attributes?.experimental_data_stream_features; + } + } + + const response = { id: packagePolicySO.id, version: packagePolicySO.version, ...packagePolicySO.attributes, }; + + // If possible, return the experimental features map for the package policy's `package` field + if (experimentalFeatures && response.package) { + response.package.experimental_data_stream_features = experimentalFeatures; + } + + return response; } public async findAllForAgentPolicy( @@ -445,6 +477,9 @@ class PackagePolicyService implements PackagePolicyServiceInterface { elasticsearch = pkgInfo.elasticsearch; } + // Handle component template/mappings updates for experimental features, e.g. synthetic source + await handleExperimentalDatastreamFeatureOptIn({ soClient, esClient, packagePolicy }); + await soClient.update<PackagePolicySOAttributes>( SAVED_OBJECT_TYPE, id, @@ -569,15 +604,23 @@ class PackagePolicyService implements PackagePolicyServiceInterface { id: string, packagePolicy?: PackagePolicy, pkgVersion?: string - ): Promise<{ packagePolicy: PackagePolicy; packageInfo: PackageInfo }> { + ): Promise<{ + packagePolicy: PackagePolicy; + packageInfo: PackageInfo; + experimentalDataStreamFeatures: ExperimentalDataStreamFeature[]; + }> { if (!packagePolicy) { packagePolicy = (await this.get(soClient, id)) ?? undefined; } + + let experimentalDataStreamFeatures: ExperimentalDataStreamFeature[] = []; + if (!pkgVersion && packagePolicy) { const installedPackage = await getInstallation({ savedObjectsClient: soClient, pkgName: packagePolicy.package!.name, }); + if (!installedPackage) { throw new IngestManagerError( i18n.translate('xpack.fleet.packagePolicy.packageNotInstalledError', { @@ -588,9 +631,13 @@ class PackagePolicyService implements PackagePolicyServiceInterface { }) ); } + pkgVersion = installedPackage.version; + experimentalDataStreamFeatures = installedPackage.experimental_data_stream_features ?? []; } + let packageInfo: PackageInfo | undefined; + if (packagePolicy) { packageInfo = await getPackageInfo({ savedObjectsClient: soClient, @@ -601,7 +648,11 @@ class PackagePolicyService implements PackagePolicyServiceInterface { this.validateUpgradePackagePolicy(id, packageInfo, packagePolicy); - return { packagePolicy: packagePolicy!, packageInfo: packageInfo! }; + return { + packagePolicy: packagePolicy!, + packageInfo: packageInfo!, + experimentalDataStreamFeatures, + }; } private validateUpgradePackagePolicy( @@ -659,8 +710,11 @@ class PackagePolicyService implements PackagePolicyServiceInterface { for (const id of ids) { try { - const { packagePolicy: currentPackagePolicy, packageInfo } = - await this.getUpgradePackagePolicyInfo(soClient, id, packagePolicy, pkgVersion); + const { + packagePolicy: currentPackagePolicy, + packageInfo, + experimentalDataStreamFeatures, + } = await this.getUpgradePackagePolicyInfo(soClient, id, packagePolicy, pkgVersion); if (currentPackagePolicy.is_managed && !options?.force) { throw new PackagePolicyRestrictionRelatedError(`Cannot upgrade package policy ${id}`); @@ -673,6 +727,7 @@ class PackagePolicyService implements PackagePolicyServiceInterface { currentPackagePolicy, result, packageInfo, + experimentalDataStreamFeatures, options ); } catch (error) { @@ -694,6 +749,7 @@ class PackagePolicyService implements PackagePolicyServiceInterface { packagePolicy: PackagePolicy, result: UpgradePackagePolicyResponse, packageInfo: PackageInfo, + experimentalDataStreamFeatures: ExperimentalDataStreamFeature[], options?: { user?: AuthenticatedUser } ) { const updatePackagePolicy = updatePackageInputs( @@ -723,6 +779,14 @@ class PackagePolicyService implements PackagePolicyServiceInterface { options, packagePolicy.package!.version ); + + // Persist any experimental feature opt-ins that come through the upgrade process to the Installation SO + await updateDatastreamExperimentalFeatures( + soClient, + packagePolicy.package!.name, + experimentalDataStreamFeatures + ); + result.push({ id, name: packagePolicy.name, @@ -738,12 +802,16 @@ class PackagePolicyService implements PackagePolicyServiceInterface { ): Promise<UpgradePackagePolicyDryRunResponseItem> { try { let packageInfo: PackageInfo; - ({ packagePolicy, packageInfo } = await this.getUpgradePackagePolicyInfo( - soClient, - id, - packagePolicy, - pkgVersion - )); + let experimentalDataStreamFeatures; + + ({ packagePolicy, packageInfo, experimentalDataStreamFeatures } = + await this.getUpgradePackagePolicyInfo(soClient, id, packagePolicy, pkgVersion)); + + // Ensure the experimental features from the Installation saved object come through on the package policy + // during an upgrade dry run + if (packagePolicy.package) { + packagePolicy.package.experimental_data_stream_features = experimentalDataStreamFeatures; + } return this.calculateDiff(soClient, packagePolicy, packageInfo); } catch (error) { @@ -766,6 +834,8 @@ class PackagePolicyService implements PackagePolicyServiceInterface { package: { ...packagePolicy.package!, version: packageInfo.version, + experimental_data_stream_features: + packagePolicy.package?.experimental_data_stream_features, }, }, packageInfo, @@ -873,6 +943,10 @@ class PackagePolicyService implements PackagePolicyServiceInterface { namespace: newPolicy.namespace ?? 'default', description: newPolicy.description ?? '', enabled: newPolicy.enabled ?? true, + package: { + ...newPP.package!, + experimental_data_stream_features: newPolicy.package?.experimental_data_stream_features, + }, policy_id: newPolicy.policy_id ?? agentPolicyId, inputs: newPolicy.inputs[0]?.streams ? newPolicy.inputs : inputs, vars: newPolicy.vars || newPP.vars, @@ -1379,7 +1453,11 @@ export interface PackagePolicyServiceInterface { getUpgradePackagePolicyInfo( soClient: SavedObjectsClientContract, id: string - ): Promise<{ packagePolicy: PackagePolicy; packageInfo: PackageInfo }>; + ): Promise<{ + packagePolicy: PackagePolicy; + packageInfo: PackageInfo; + experimentalDataStreamFeatures: ExperimentalDataStreamFeature[]; + }>; } export const packagePolicyService: PackagePolicyServiceInterface = new PackagePolicyService(); diff --git a/x-pack/plugins/fleet/server/types/models/package_policy.ts b/x-pack/plugins/fleet/server/types/models/package_policy.ts index 5220f18380dd16..bddce3acbc847e 100644 --- a/x-pack/plugins/fleet/server/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/models/package_policy.ts @@ -87,6 +87,16 @@ const PackagePolicyBaseSchema = { name: schema.string(), title: schema.string(), version: schema.string(), + experimental_data_stream_features: schema.maybe( + schema.arrayOf( + schema.object({ + data_stream: schema.string(), + features: schema.object({ + synthetic_source: schema.boolean(), + }), + }) + ) + ), }) ), // Deprecated TODO create remove issue @@ -111,6 +121,14 @@ const CreatePackagePolicyProps = { name: schema.string(), title: schema.maybe(schema.string()), version: schema.string(), + experimental_data_stream_features: schema.maybe( + schema.arrayOf( + schema.object({ + data_stream: schema.string(), + features: schema.object({ synthetic_source: schema.boolean() }), + }) + ) + ), }) ), // Deprecated TODO create remove issue From f236196ad24dc1510c1a183002b352b3db89659d Mon Sep 17 00:00:00 2001 From: Julian Gernun <julian.gernun@elastic.co> Date: Mon, 12 Sep 2022 16:05:23 +0200 Subject: [PATCH 067/144] [RAM] Category fields endpoint (#138245) * first commit * get auth index and try field caps * use esClient * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * wait for promise to finish * format field capabilities * add simplier browserFields mapper * update response * refactor * types and refactor * remove browser fields dependency * update fn name * update types * update imported type package * update mock object * error message for no o11y alert indices * add endpoint integration test * activate commented tests * add unit test * comment uncommented tests * fix tests * review by Xavier * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * update param names + right type Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Xavier Mouligneau <xavier.mouligneau@elastic.co> --- .../alert_data_client/alerts_client.mock.ts | 1 + .../server/alert_data_client/alerts_client.ts | 22 +++++ .../alert_data_client/browser_fields/index.ts | 46 ++++++++++ .../routes/__mocks__/request_responses.ts | 7 ++ .../get_browser_fields_by_feature_id.test.ts | 65 ++++++++++++++ .../get_browser_fields_by_feature_id.ts | 84 +++++++++++++++++++ .../rule_registry/server/routes/index.ts | 2 + x-pack/plugins/rule_registry/server/types.ts | 9 ++ .../basic/get_browser_fields_by_feature_id.ts | 71 ++++++++++++++++ .../security_and_spaces/tests/basic/index.ts | 1 + 10 files changed, 308 insertions(+) create mode 100644 x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts create mode 100644 x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts create mode 100644 x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts create mode 100644 x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts index 3c3edf4e988ec7..59db45aff0fa2f 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.mock.ts @@ -19,6 +19,7 @@ const createAlertsClientMock = () => { bulkUpdate: jest.fn(), find: jest.fn(), getFeatureIdsByRegistrationContexts: jest.fn(), + getBrowserFields: jest.fn(), }; return mocked; }; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 348dfebed1fcd7..31731cecbeccb2 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -30,6 +30,7 @@ import { } from '@kbn/alerting-plugin/server'; import { Logger, ElasticsearchClient, EcsEventOutcome } from '@kbn/core/server'; import { AuditLogger } from '@kbn/security-plugin/server'; +import { IndexPatternsFetcher } from '@kbn/data-plugin/server'; import { alertAuditEvent, operationAlertAuditActionMap } from './audit_events'; import { ALERT_WORKFLOW_STATUS, @@ -40,6 +41,8 @@ import { import { ParsedTechnicalFields } from '../../common/parse_technical_fields'; import { Dataset, IRuleDataService } from '../rule_data_plugin_service'; import { getAuthzFilter, getSpacesFilter } from '../lib'; +import { fieldDescriptorToBrowserFieldMapper } from './browser_fields'; +import { BrowserFields } from '../types'; // TODO: Fix typings https://github.com/elastic/kibana/issues/101776 type NonNullableProps<Obj extends {}, Props extends keyof Obj> = Omit<Obj, Props> & { @@ -716,4 +719,23 @@ export class AlertsClient { throw Boom.failedDependency(errMessage); } } + + async getBrowserFields({ + indices, + metaFields, + allowNoIndex, + }: { + indices: string[]; + metaFields: string[]; + allowNoIndex: boolean; + }): Promise<BrowserFields> { + const indexPatternsFetcherAsInternalUser = new IndexPatternsFetcher(this.esClient); + const { fields } = await indexPatternsFetcherAsInternalUser.getFieldsForWildcard({ + pattern: indices, + metaFields, + fieldCapsOptions: { allow_no_indices: allowNoIndex }, + }); + + return fieldDescriptorToBrowserFieldMapper(fields); + } } diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts b/x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts new file mode 100644 index 00000000000000..074c3f60006c87 --- /dev/null +++ b/x-pack/plugins/rule_registry/server/alert_data_client/browser_fields/index.ts @@ -0,0 +1,46 @@ +/* + * 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 { FieldDescriptor } from '@kbn/data-views-plugin/server'; +import { BrowserField, BrowserFields } from '../../types'; + +const getFieldCategory = (fieldCapability: FieldDescriptor) => { + const name = fieldCapability.name.split('.'); + + if (name.length === 1) { + return 'base'; + } + + return name[0]; +}; + +const browserFieldFactory = ( + fieldCapability: FieldDescriptor, + category: string +): { [fieldName in string]: BrowserField } => { + return { + [fieldCapability.name]: { + ...fieldCapability, + category, + }, + }; +}; + +export const fieldDescriptorToBrowserFieldMapper = (fields: FieldDescriptor[]): BrowserFields => { + return fields.reduce((browserFields: BrowserFields, field: FieldDescriptor) => { + const category = getFieldCategory(field); + const browserField = browserFieldFactory(field, category); + + if (browserFields[category]) { + browserFields[category] = { fields: { ...browserFields[category].fields, ...browserField } }; + } else { + browserFields[category] = { fields: browserField }; + } + + return browserFields; + }, {}); +}; diff --git a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts index b750b37aa51b5b..3fad5f9309532a 100644 --- a/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/rule_registry/server/routes/__mocks__/request_responses.ts @@ -39,3 +39,10 @@ export const getReadFeatureIdsRequest = () => path: `${BASE_RAC_ALERTS_API_PATH}/_feature_ids`, query: { registrationContext: ['security'] }, }); + +export const getO11yBrowserFields = () => + requestMock.create({ + method: 'get', + path: `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, + query: { featureIds: ['apm', 'logs'] }, + }); diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts new file mode 100644 index 00000000000000..49e559c9f4c24f --- /dev/null +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.test.ts @@ -0,0 +1,65 @@ +/* + * 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 { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; +import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_feature_id'; +import { requestContextMock } from './__mocks__/request_context'; +import { getO11yBrowserFields } from './__mocks__/request_responses'; +import { requestMock, serverMock } from './__mocks__/server'; + +describe('getBrowserFieldsByFeatureId', () => { + let server: ReturnType<typeof serverMock.create>; + let { clients, context } = requestContextMock.createTools(); + const path = `${BASE_RAC_ALERTS_API_PATH}/browser_fields`; + + beforeEach(async () => { + server = serverMock.create(); + ({ clients, context } = requestContextMock.createTools()); + }); + + describe('when racClient returns o11y indices', () => { + beforeEach(() => { + clients.rac.getAuthorizedAlertsIndices.mockResolvedValue([ + '.alerts-observability.logs.alerts-default', + ]); + + getBrowserFieldsByFeatureId(server.router); + }); + + test('route registered', async () => { + const response = await server.inject(getO11yBrowserFields(), context); + + expect(response.status).toEqual(200); + }); + + test('rejects invalid featureId type', async () => { + await expect( + server.inject( + requestMock.create({ + method: 'get', + path, + query: { featureIds: undefined }, + }), + context + ) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Request was rejected with message: 'Invalid value \\"undefined\\" supplied to \\"featureIds\\"'"` + ); + }); + + test('returns error status if rac client "getAuthorizedAlertsIndices" fails', async () => { + clients.rac.getAuthorizedAlertsIndices.mockRejectedValue(new Error('Unable to get index')); + const response = await server.inject(getO11yBrowserFields(), context); + + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + attributes: { success: false }, + message: 'Unable to get index', + }); + }); + }); +}); diff --git a/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts new file mode 100644 index 00000000000000..6b2d59c824ab3d --- /dev/null +++ b/x-pack/plugins/rule_registry/server/routes/get_browser_fields_by_feature_id.ts @@ -0,0 +1,84 @@ +/* + * 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 { IRouter } from '@kbn/core/server'; +import { transformError } from '@kbn/securitysolution-es-utils'; +import * as t from 'io-ts'; + +import { RacRequestHandlerContext } from '../types'; +import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; +import { buildRouteValidation } from './utils/route_validation'; + +export const getBrowserFieldsByFeatureId = (router: IRouter<RacRequestHandlerContext>) => { + router.get( + { + path: `${BASE_RAC_ALERTS_API_PATH}/browser_fields`, + validate: { + query: buildRouteValidation( + t.exact( + t.type({ + featureIds: t.union([t.string, t.array(t.string)]), + }) + ) + ), + }, + options: { + tags: ['access:rac'], + }, + }, + async (context, request, response) => { + try { + const racContext = await context.rac; + const alertsClient = await racContext.getAlertsClient(); + const { featureIds = [] } = request.query; + + const indices = await alertsClient.getAuthorizedAlertsIndices( + Array.isArray(featureIds) ? featureIds : [featureIds] + ); + const o11yIndices = + indices?.filter((index) => index.startsWith('.alerts-observability')) ?? []; + if (o11yIndices.length === 0) { + return response.notFound({ + body: { + message: `No alerts-observability indices found for featureIds [${featureIds}]`, + attributes: { success: false }, + }, + }); + } + + const browserFields = await alertsClient.getBrowserFields({ + indices: o11yIndices, + metaFields: ['_id', '_index'], + allowNoIndex: true, + }); + + return response.ok({ + body: browserFields, + }); + } catch (error) { + const formatedError = transformError(error); + const contentType = { + 'content-type': 'application/json', + }; + const defaultedHeaders = { + ...contentType, + }; + + return response.customError({ + headers: defaultedHeaders, + statusCode: formatedError.statusCode, + body: { + message: formatedError.message, + attributes: { + success: false, + }, + }, + }); + } + } + ); +}; diff --git a/x-pack/plugins/rule_registry/server/routes/index.ts b/x-pack/plugins/rule_registry/server/routes/index.ts index 638fb4e432412e..a693de9b2fa4c4 100644 --- a/x-pack/plugins/rule_registry/server/routes/index.ts +++ b/x-pack/plugins/rule_registry/server/routes/index.ts @@ -13,6 +13,7 @@ import { getAlertsIndexRoute } from './get_alert_index'; import { bulkUpdateAlertsRoute } from './bulk_update_alerts'; import { findAlertsByQueryRoute } from './find'; import { getFeatureIdsByRegistrationContexts } from './get_feature_ids_by_registration_contexts'; +import { getBrowserFieldsByFeatureId } from './get_browser_fields_by_feature_id'; export function defineRoutes(router: IRouter<RacRequestHandlerContext>) { getAlertByIdRoute(router); @@ -21,4 +22,5 @@ export function defineRoutes(router: IRouter<RacRequestHandlerContext>) { bulkUpdateAlertsRoute(router); findAlertsByQueryRoute(router); getFeatureIdsByRegistrationContexts(router); + getBrowserFieldsByFeatureId(router); } diff --git a/x-pack/plugins/rule_registry/server/types.ts b/x-pack/plugins/rule_registry/server/types.ts index 6a7d5b849c771e..f466a7f8cf495a 100644 --- a/x-pack/plugins/rule_registry/server/types.ts +++ b/x-pack/plugins/rule_registry/server/types.ts @@ -13,6 +13,7 @@ import { RuleTypeState, } from '@kbn/alerting-plugin/common'; import { RuleExecutorOptions, RuleExecutorServices, RuleType } from '@kbn/alerting-plugin/server'; +import { FieldSpec } from '@kbn/data-plugin/common'; import { AlertsClient } from './alert_data_client/alerts_client'; type SimpleAlertType< @@ -71,3 +72,11 @@ export interface RacApiRequestHandlerContext { export type RacRequestHandlerContext = CustomRequestHandlerContext<{ rac: RacApiRequestHandlerContext; }>; + +export type BrowserField = FieldSpec & { + category: string; +}; + +export type BrowserFields = { + [category in string]: { fields: { [fieldName in string]: BrowserField } }; +}; diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts new file mode 100644 index 00000000000000..6acbc14a473524 --- /dev/null +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_browser_fields_by_feature_id.ts @@ -0,0 +1,71 @@ +/* + * 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 expect from '@kbn/expect'; + +import { superUser, obsOnlySpacesAll, secOnlyRead } from '../../../common/lib/authentication/users'; +import type { User } from '../../../common/lib/authentication/types'; +import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { getSpaceUrlPrefix } from '../../../common/lib/authentication/spaces'; + +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const esArchiver = getService('esArchiver'); + const SPACE1 = 'space1'; + const TEST_URL = '/internal/rac/alerts/browser_fields'; + + const getBrowserFieldsByFeatureId = async ( + user: User, + featureIds: string[], + expectedStatusCode: number = 200 + ) => { + const resp = await supertestWithoutAuth + .get(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}`) + .query({ featureIds }) + .auth(user.username, user.password) + .set('kbn-xsrf', 'true') + .expect(expectedStatusCode); + return resp.body; + }; + + describe('Alert - Get browser fields by featureId', () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); + }); + + describe('Users:', () => { + it(`${obsOnlySpacesAll.username} should be able to get browser fields for o11y featureIds`, async () => { + const browserFields = await getBrowserFieldsByFeatureId(obsOnlySpacesAll, [ + 'apm', + 'infrastructure', + 'logs', + 'uptime', + ]); + expect(Object.keys(browserFields)).to.eql(['base']); + }); + + it(`${superUser.username} should be able to get browser fields for o11y featureIds`, async () => { + const browserFields = await getBrowserFieldsByFeatureId(superUser, [ + 'apm', + 'infrastructure', + 'logs', + 'uptime', + ]); + expect(Object.keys(browserFields)).to.eql(['base']); + }); + + it(`${superUser.username} should NOT be able to get browser fields for siem featureId`, async () => { + await getBrowserFieldsByFeatureId(superUser, ['siem'], 404); + }); + + it(`${secOnlyRead.username} should NOT be able to get browser fields for siem featureId`, async () => { + await getBrowserFieldsByFeatureId(secOnlyRead, ['siem'], 404); + }); + }); + }); +}; diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts index e96239f37cdfbf..e1046b2dca6d76 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts @@ -29,5 +29,6 @@ export default ({ loadTestFile, getService }: FtrProviderContext): void => { loadTestFile(require.resolve('./get_alerts_index')); loadTestFile(require.resolve('./find_alerts')); loadTestFile(require.resolve('./search_strategy')); + loadTestFile(require.resolve('./get_browser_fields_by_feature_id')); }); }; From 0f284959f3af10943f5764583f4378d26f0c7173 Mon Sep 17 00:00:00 2001 From: Christos Nasikas <christos.nasikas@elastic.co> Date: Mon, 12 Sep 2022 17:08:00 +0300 Subject: [PATCH 068/144] [Cases] Add the ability to delete attachments (#140191) * Add delete action for registered attachments * PR feedback --- .../user_actions/comment/comment.test.tsx | 85 +++++++++++++++++++ .../user_actions/comment/comment.tsx | 4 + .../comment/external_reference.tsx | 7 +- .../comment/persistable_state.tsx | 7 +- .../comment/registered_attachments.tsx | 22 ++++- .../user_actions/content_toolbar.tsx | 20 +++-- .../user_actions/property_actions.test.tsx | 34 ++++++++ .../user_actions/property_actions.tsx | 56 ++++++++---- 8 files changed, 207 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx index 66dbf74e6815b7..f8dba47578d72b 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/comment.test.tsx @@ -8,6 +8,8 @@ import React from 'react'; import { EuiCommentList } from '@elastic/eui'; import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import { Actions } from '../../../../common/api'; import { @@ -263,6 +265,47 @@ describe('createCommentUserActionBuilder', () => { expect(result.getByTestId('comment-externalReference-.test')).toBeInTheDocument(); expect(screen.getByText('Attachment actions')).toBeInTheDocument(); }); + + it('deletes the attachment correctly', async () => { + const externalReferenceAttachmentTypeRegistry = new ExternalReferenceAttachmentTypeRegistry(); + externalReferenceAttachmentTypeRegistry.register(getExternalReferenceAttachment()); + + const userAction = getExternalReferenceUserAction(); + const builder = createCommentUserActionBuilder({ + ...builderArgs, + externalReferenceAttachmentTypeRegistry, + caseData: { + ...builderArgs.caseData, + comments: [externalReferenceAttachment], + }, + userAction, + }); + + const createdUserAction = builder.build(); + const result = appMockRender.render(<EuiCommentList comments={createdUserAction} />); + + expect(result.getByTestId('comment-externalReference-.test')).toBeInTheDocument(); + expect(result.getByTestId('property-actions')).toBeInTheDocument(); + + userEvent.click(result.getByTestId('property-actions-ellipses')); + await waitForEuiPopoverOpen(); + + expect(result.queryByTestId('property-actions-trash')).toBeInTheDocument(); + + userEvent.click(result.getByTestId('property-actions-trash')); + + await waitFor(() => { + expect(result.queryByTestId('property-actions-confirm-modal')).toBeInTheDocument(); + }); + + userEvent.click(result.getByText('Delete')); + + await waitFor(() => { + expect(builderArgs.handleDeleteComment).toHaveBeenCalledWith( + 'external-reference-comment-id' + ); + }); + }); }); describe('Persistable state', () => { @@ -398,5 +441,47 @@ describe('createCommentUserActionBuilder', () => { expect(result.getByTestId('comment-persistableState-.test')).toBeInTheDocument(); expect(screen.getByText('Attachment actions')).toBeInTheDocument(); }); + + it('deletes the attachment correctly', async () => { + const attachment = getPersistableStateAttachment(); + const persistableStateAttachmentTypeRegistry = new PersistableStateAttachmentTypeRegistry(); + persistableStateAttachmentTypeRegistry.register(attachment); + + const userAction = getPersistableStateUserAction(); + const builder = createCommentUserActionBuilder({ + ...builderArgs, + persistableStateAttachmentTypeRegistry, + caseData: { + ...builderArgs.caseData, + comments: [persistableStateAttachment], + }, + userAction, + }); + + const createdUserAction = builder.build(); + const result = appMockRender.render(<EuiCommentList comments={createdUserAction} />); + + expect(result.getByTestId('comment-persistableState-.test')).toBeInTheDocument(); + expect(result.getByTestId('property-actions')).toBeInTheDocument(); + + userEvent.click(result.getByTestId('property-actions-ellipses')); + await waitForEuiPopoverOpen(); + + expect(result.queryByTestId('property-actions-trash')).toBeInTheDocument(); + + userEvent.click(result.getByTestId('property-actions-trash')); + + await waitFor(() => { + expect(result.queryByTestId('property-actions-confirm-modal')).toBeInTheDocument(); + }); + + userEvent.click(result.getByText('Delete')); + + await waitFor(() => { + expect(builderArgs.handleDeleteComment).toHaveBeenCalledWith( + 'persistable-state-comment-id' + ); + }); + }); }); }); diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx index d559a0981ad690..e04738a962686e 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/comment.tsx @@ -114,6 +114,8 @@ const getCreateCommentUserAction = ({ comment, externalReferenceAttachmentTypeRegistry, caseData, + isLoading: loadingCommentIds.includes(comment.id), + handleDeleteComment, }); return externalReferenceBuilder.build(); @@ -124,6 +126,8 @@ const getCreateCommentUserAction = ({ comment, persistableStateAttachmentTypeRegistry, caseData, + isLoading: loadingCommentIds.includes(comment.id), + handleDeleteComment, }); return persistableBuilder.build(); diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx index 10b676be711b71..f2b5987d8cb1df 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/external_reference.tsx @@ -12,9 +12,10 @@ import { createRegisteredAttachmentUserActionBuilder } from './registered_attach type BuilderArgs = Pick< UserActionBuilderArgs, - 'userAction' | 'externalReferenceAttachmentTypeRegistry' | 'caseData' + 'userAction' | 'externalReferenceAttachmentTypeRegistry' | 'caseData' | 'handleDeleteComment' > & { comment: SnakeToCamelCase<CommentResponseExternalReferenceType>; + isLoading: boolean; }; export const createExternalReferenceAttachmentUserActionBuilder = ({ @@ -22,12 +23,16 @@ export const createExternalReferenceAttachmentUserActionBuilder = ({ comment, externalReferenceAttachmentTypeRegistry, caseData, + isLoading, + handleDeleteComment, }: BuilderArgs): ReturnType<UserActionBuilder> => { return createRegisteredAttachmentUserActionBuilder({ userAction, comment, registry: externalReferenceAttachmentTypeRegistry, caseData, + handleDeleteComment, + isLoading, getId: () => comment.externalReferenceAttachmentTypeId, getAttachmentViewProps: () => ({ externalReferenceId: comment.externalReferenceId, diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx index 80e4d0d3743ce0..2d5cfa91e1500a 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/persistable_state.tsx @@ -12,9 +12,10 @@ import { createRegisteredAttachmentUserActionBuilder } from './registered_attach type BuilderArgs = Pick< UserActionBuilderArgs, - 'userAction' | 'persistableStateAttachmentTypeRegistry' | 'caseData' + 'userAction' | 'persistableStateAttachmentTypeRegistry' | 'caseData' | 'handleDeleteComment' > & { comment: SnakeToCamelCase<CommentResponseTypePersistableState>; + isLoading: boolean; }; export const createPersistableStateAttachmentUserActionBuilder = ({ @@ -22,12 +23,16 @@ export const createPersistableStateAttachmentUserActionBuilder = ({ comment, persistableStateAttachmentTypeRegistry, caseData, + isLoading, + handleDeleteComment, }: BuilderArgs): ReturnType<UserActionBuilder> => { return createRegisteredAttachmentUserActionBuilder({ userAction, comment, registry: persistableStateAttachmentTypeRegistry, caseData, + handleDeleteComment, + isLoading, getId: () => comment.persistableStateAttachmentTypeId, getAttachmentViewProps: () => ({ persistableStateAttachmentTypeId: comment.persistableStateAttachmentTypeId, diff --git a/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx b/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx index 6d07d9111fc8a2..446cb6114e97e8 100644 --- a/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/comment/registered_attachments.tsx @@ -22,12 +22,17 @@ import { UserActionBuilder, UserActionBuilderArgs } from '../types'; import { UserActionTimestamp } from '../timestamp'; import { SnakeToCamelCase } from '../../../../common/types'; import { UserActionUsernameWithAvatar } from '../avatar_username'; -import { UserActionCopyLink } from '../copy_link'; import { ATTACHMENT_NOT_REGISTERED_ERROR, DEFAULT_EVENT_ATTACHMENT_TITLE } from './translations'; +import { UserActionContentToolbar } from '../content_toolbar'; +import * as i18n from '../translations'; -type BuilderArgs<C, R> = Pick<UserActionBuilderArgs, 'userAction' | 'caseData'> & { +type BuilderArgs<C, R> = Pick< + UserActionBuilderArgs, + 'userAction' | 'caseData' | 'handleDeleteComment' +> & { comment: SnakeToCamelCase<C>; registry: R; + isLoading: boolean; getId: () => string; getAttachmentViewProps: () => object; }; @@ -64,8 +69,10 @@ export const createRegisteredAttachmentUserActionBuilder = < comment, registry, caseData, + isLoading, getId, getAttachmentViewProps, + handleDeleteComment, }: BuilderArgs<C, R>): ReturnType<UserActionBuilder> => ({ // TODO: Fix this manually. Issue #123375 // eslint-disable-next-line react/display-name @@ -122,8 +129,15 @@ export const createRegisteredAttachmentUserActionBuilder = < timelineAvatar: attachmentViewObject.timelineAvatar, actions: ( <> - <UserActionCopyLink id={comment.id} /> - {attachmentViewObject.actions} + <UserActionContentToolbar + actions={['delete']} + id={comment.id} + deleteLabel={i18n.DELETE_COMMENT} + deleteConfirmTitle={i18n.DELETE_COMMENT_TITLE} + isLoading={isLoading} + onDelete={() => handleDeleteComment(comment.id)} + extraActions={attachmentViewObject.actions} + /> </> ), children: renderer(props), diff --git a/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx b/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx index e23a4efa2f0a21..b824f6f20276f0 100644 --- a/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/content_toolbar.tsx @@ -6,32 +6,36 @@ */ import React, { memo } from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiCommentProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { UserActionCopyLink } from './copy_link'; -import { UserActionPropertyActions } from './property_actions'; +import { Actions, UserActionPropertyActions } from './property_actions'; export interface UserActionContentToolbarProps { - commentMarkdown: string; + commentMarkdown?: string; id: string; - editLabel: string; + actions?: Actions; + editLabel?: string; deleteLabel?: string; deleteConfirmTitle?: string; - quoteLabel: string; + quoteLabel?: string; isLoading: boolean; - onEdit: (id: string) => void; - onQuote: (id: string) => void; + extraActions?: EuiCommentProps['actions']; + onEdit?: (id: string) => void; + onQuote?: (id: string) => void; onDelete?: (id: string) => void; } const UserActionContentToolbarComponent = ({ commentMarkdown, id, + actions, editLabel, deleteLabel, deleteConfirmTitle, quoteLabel, isLoading, + extraActions, onEdit, onQuote, onDelete, @@ -43,6 +47,7 @@ const UserActionContentToolbarComponent = ({ <EuiFlexItem grow={false}> <UserActionPropertyActions id={id} + actions={actions} editLabel={editLabel} quoteLabel={quoteLabel} deleteLabel={deleteLabel} @@ -54,6 +59,7 @@ const UserActionContentToolbarComponent = ({ commentMarkdown={commentMarkdown} /> </EuiFlexItem> + {extraActions != null ? <EuiFlexItem grow={false}>{extraActions}</EuiFlexItem> : null} </EuiFlexGroup> ); UserActionContentToolbarComponent.displayName = 'UserActionContentToolbar'; diff --git a/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx b/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx index 2f52656c9fca96..01a4605f1651f4 100644 --- a/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/property_actions.test.tsx @@ -213,4 +213,38 @@ describe('UserActionPropertyActions ', () => { expect(onDelete).toHaveBeenCalledWith(deleteProps.id); }); }); + + describe('action filtering', () => { + const tests = [ + ['edit', 'pencil'], + ['delete', 'trash'], + ['quote', 'quote'], + ] as const; + + it.each(tests)('renders action %s', async (action, type) => { + const renderResult = render( + <TestProviders> + <UserActionPropertyActions + {...props} + onDelete={() => {}} + deleteLabel={'test'} + actions={[action]} + /> + </TestProviders> + ); + + expect(renderResult.queryByTestId('user-action-title-loading')).not.toBeInTheDocument(); + expect(renderResult.getByTestId('property-actions')).toBeInTheDocument(); + + userEvent.click(renderResult.getByTestId('property-actions-ellipses')); + await waitForEuiPopoverOpen(); + + expect(renderResult.queryByTestId(`property-actions-${type}`)).toBeInTheDocument(); + /** + * This check ensures that no other action is rendered. There is + * one button to open the popover and one button for the action + **/ + expect(await renderResult.findAllByRole('button')).toHaveLength(2); + }); + }); }); diff --git a/x-pack/plugins/cases/public/components/user_actions/property_actions.tsx b/x-pack/plugins/cases/public/components/user_actions/property_actions.tsx index 13273346241e53..132b824109e519 100644 --- a/x-pack/plugins/cases/public/components/user_actions/property_actions.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/property_actions.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { noop } from 'lodash'; import React, { memo, useMemo, useCallback, useState } from 'react'; import { EuiConfirmModal, EuiLoadingSpinner } from '@elastic/eui'; @@ -13,33 +14,48 @@ import { useLensOpenVisualization } from '../markdown_editor/plugins/lens/use_le import { CANCEL_BUTTON, CONFIRM_BUTTON } from './translations'; import { useCasesContext } from '../cases_context/use_cases_context'; +const totalActions = { + edit: 'edit', + delete: 'delete', + quote: 'quote', + showLensEditor: 'showLensEditor', +} as const; + +const availableActions = Object.keys(totalActions) as Array<keyof typeof totalActions>; + +export type Actions = typeof availableActions; + export interface UserActionPropertyActionsProps { id: string; - editLabel: string; + actions?: Actions; + editLabel?: string; deleteLabel?: string; deleteConfirmTitle?: string; - quoteLabel: string; + quoteLabel?: string; isLoading: boolean; - onEdit: (id: string) => void; + onEdit?: (id: string) => void; onDelete?: (id: string) => void; - onQuote: (id: string) => void; - commentMarkdown: string; + onQuote?: (id: string) => void; + commentMarkdown?: string; } const UserActionPropertyActionsComponent = ({ id, - editLabel, - quoteLabel, - deleteLabel, + actions = availableActions, + editLabel = '', + quoteLabel = '', + deleteLabel = '', deleteConfirmTitle, isLoading, - onEdit, + onEdit = noop, onDelete, - onQuote, + onQuote = noop, commentMarkdown, }: UserActionPropertyActionsProps) => { const { permissions } = useCasesContext(); - const { canUseEditor, actionConfig } = useLensOpenVisualization({ comment: commentMarkdown }); + const { canUseEditor, actionConfig } = useLensOpenVisualization({ + comment: commentMarkdown ?? '', + }); const onEditClick = useCallback(() => onEdit(id), [id, onEdit]); const onQuoteClick = useCallback(() => onQuote(id), [id, onQuote]); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); @@ -60,10 +76,19 @@ const UserActionPropertyActionsComponent = ({ }, []); const propertyActions = useMemo(() => { - const showEditPencilIcon = permissions.update; - const showTrashIcon = permissions.delete && deleteLabel && onDelete; - const showQuoteIcon = permissions.create; - const showLensEditor = permissions.update && canUseEditor && actionConfig; + const showEditPencilIcon = permissions.update && actions.includes(totalActions.edit); + + const showTrashIcon = Boolean( + permissions.delete && deleteLabel && onDelete && actions.includes(totalActions.delete) + ); + + const showQuoteIcon = permissions.create && actions.includes(totalActions.quote); + + const showLensEditor = + permissions.update && + canUseEditor && + actionConfig && + actions.includes(totalActions.showLensEditor); return [ ...(showEditPencilIcon @@ -99,6 +124,7 @@ const UserActionPropertyActionsComponent = ({ permissions.update, permissions.delete, permissions.create, + actions, deleteLabel, onDelete, canUseEditor, From b02391275c496afe18433334c0efa45db26f80ca Mon Sep 17 00:00:00 2001 From: Christos Nasikas <christos.nasikas@elastic.co> Date: Mon, 12 Sep 2022 17:29:14 +0300 Subject: [PATCH 069/144] [Cases] Show only cases from solutions with 'All' privilege in the cases modal (#140032) * Fix bug * Improvements * Fix permissions * Fix tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../all_cases/all_cases_list.test.tsx | 104 ++++++++++++++++++ .../components/all_cases/all_cases_list.tsx | 25 ++++- .../all_cases/table_filters.test.tsx | 15 +++ .../components/all_cases/table_filters.tsx | 2 +- .../components/app/use_available_owners.ts | 4 +- .../components/filter_popover/index.tsx | 4 +- 6 files changed, 146 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx index c38408c8f54173..5a77eb7155b86e 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.test.tsx @@ -898,4 +898,108 @@ describe('AllCasesListGeneric', () => { expect(alertCounts.length).toBeGreaterThan(0); }); + + describe('Solutions', () => { + it('should set the owner to all available solutions when deselecting all solutions', async () => { + const { getByTestId } = appMockRenderer.render( + <TestProviders owner={[]}> + <AllCasesList /> + </TestProviders> + ); + + expect(useGetCasesMock).toHaveBeenCalledWith({ + filterOptions: { + search: '', + searchFields: [], + severity: 'all', + reporters: [], + status: 'all', + tags: [], + assignees: [], + owner: ['securitySolution', 'observability'], + }, + queryParams: { page: 1, perPage: 5, sortField: 'createdAt', sortOrder: 'desc' }, + }); + + userEvent.click(getByTestId('options-filter-popover-button-Solution')); + + await waitForEuiPopoverOpen(); + + userEvent.click( + getByTestId(`options-filter-popover-item-${SECURITY_SOLUTION_OWNER}`), + undefined, + { + skipPointerEventsCheck: true, + } + ); + + expect(useGetCasesMock).toBeCalledWith({ + filterOptions: { + search: '', + searchFields: [], + severity: 'all', + reporters: [], + status: 'all', + tags: [], + assignees: [], + owner: ['securitySolution'], + }, + queryParams: { page: 1, perPage: 5, sortField: 'createdAt', sortOrder: 'desc' }, + }); + + userEvent.click( + getByTestId(`options-filter-popover-item-${SECURITY_SOLUTION_OWNER}`), + undefined, + { + skipPointerEventsCheck: true, + } + ); + + expect(useGetCasesMock).toHaveBeenLastCalledWith({ + filterOptions: { + search: '', + searchFields: [], + severity: 'all', + reporters: [], + status: 'all', + tags: [], + assignees: [], + owner: ['securitySolution', 'observability'], + }, + queryParams: { page: 1, perPage: 5, sortField: 'createdAt', sortOrder: 'desc' }, + }); + }); + + it('should hide the solutions filter if the owner is provided', async () => { + const { queryByTestId } = appMockRenderer.render( + <TestProviders owner={[SECURITY_SOLUTION_OWNER]}> + <AllCasesList /> + </TestProviders> + ); + + expect(queryByTestId('options-filter-popover-button-Solution')).toBeFalsy(); + }); + + it('should call useGetCases with the correct owner on initial render', async () => { + appMockRenderer.render( + <TestProviders owner={[SECURITY_SOLUTION_OWNER]}> + <AllCasesList /> + </TestProviders> + ); + + expect(useGetCasesMock).toHaveBeenCalledWith({ + filterOptions: { + search: '', + searchFields: [], + severity: 'all', + reporters: [], + status: 'all', + tags: [], + assignees: [], + owner: ['securitySolution'], + }, + queryParams: { page: 1, perPage: 5, sortField: 'createdAt', sortOrder: 'desc' }, + }); + }); + }); }); diff --git a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx index ce38c82f083841..0bc5e9b14b29a7 100644 --- a/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/all_cases_list.tsx @@ -42,6 +42,7 @@ import { USER_PROFILES_BULK_GET_CACHE_KEY, USER_PROFILES_CACHE_KEY, } from '../../containers/constants'; +import { getAllPermissionsExceptFrom } from '../../utils/permissions'; const ProgressLoader = styled(EuiProgress)` ${({ $isShow }: { $isShow: boolean }) => @@ -69,7 +70,7 @@ export interface AllCasesListProps { export const AllCasesList = React.memo<AllCasesListProps>( ({ hiddenStatuses = [], isSelectorView = false, onRowClick, doRefresh }) => { const { owner, permissions } = useCasesContext(); - const availableSolutions = useAvailableCasesOwners(); + const availableSolutions = useAvailableCasesOwners(getAllPermissionsExceptFrom('delete')); const [refresh, setRefresh] = useState(0); const hasOwner = !!owner.length; @@ -77,7 +78,7 @@ export const AllCasesList = React.memo<AllCasesListProps>( const firstAvailableStatus = head(difference(caseStatuses, hiddenStatuses)); const initialFilterOptions = { ...(!isEmpty(hiddenStatuses) && firstAvailableStatus && { status: firstAvailableStatus }), - owner: hasOwner ? owner : [], + owner: hasOwner ? owner : availableSolutions, }; const [filterOptions, setFilterOptions] = useState<FilterOptions>({ ...DEFAULT_FILTER_OPTIONS, @@ -209,10 +210,28 @@ export const AllCasesList = React.memo<AllCasesListProps>( setFilterOptions((prevFilterOptions) => ({ ...prevFilterOptions, ...newFilterOptions, + /** + * If the user selects and deselects all solutions + * then the owner is set to an empty array. This results in fetching all cases the user has access to including + * the ones with read access. We want to show only the cases the user has full access to. + * For that reason we fallback to availableSolutions if the owner is empty. + * + * If the consumer of cases has passed an owner we fallback to the provided owner + */ + ...(newFilterOptions.owner != null && !hasOwner + ? { + owner: + newFilterOptions.owner.length === 0 ? availableSolutions : newFilterOptions.owner, + } + : newFilterOptions.owner != null && hasOwner + ? { + owner: newFilterOptions.owner.length === 0 ? owner : newFilterOptions.owner, + } + : {}), })); refreshCases(false); }, - [deselectCases, setFilterOptions, refreshCases, setQueryParams] + [deselectCases, refreshCases, hasOwner, availableSolutions, owner] ); /** diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx index 23a8772852e17d..2d6f4076f6cf30 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.test.tsx @@ -272,6 +272,21 @@ describe('CasesTableFilters ', () => { expect(onFilterChanged).toBeCalledWith({ owner: [] }); }); + + it('does not select a solution on initial render', () => { + const wrapper = mount( + <TestProviders> + <CasesTableFilters + {...props} + availableSolutions={[SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER]} + /> + </TestProviders> + ); + + expect( + wrapper.find(`[data-test-subj="options-filter-popover-button-Solution"]`).first().props() + ).toEqual(expect.objectContaining({ hasActiveFilters: false })); + }); }); describe('create case button', () => { diff --git a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx index 25da22f9be1686..d35ff00058b999 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table_filters.tsx @@ -68,7 +68,7 @@ const CasesTableFiltersComponent = ({ }: CasesTableFiltersProps) => { const [search, setSearch] = useState(initial.search); const [selectedTags, setSelectedTags] = useState(initial.tags); - const [selectedOwner, setSelectedOwner] = useState(initial.owner); + const [selectedOwner, setSelectedOwner] = useState([]); const [selectedAssignees, setSelectedAssignees] = useState<UserProfileWithAvatar[]>([]); const { data: tags = [], refetch: fetchTags } = useGetTags(CASE_LIST_CACHE_KEY); diff --git a/x-pack/plugins/cases/public/components/app/use_available_owners.ts b/x-pack/plugins/cases/public/components/app/use_available_owners.ts index 9e593fa6c282ad..c981a6a01e063f 100644 --- a/x-pack/plugins/cases/public/components/app/use_available_owners.ts +++ b/x-pack/plugins/cases/public/components/app/use_available_owners.ts @@ -24,12 +24,12 @@ export const useAvailableCasesOwners = ( const { capabilities: kibanaCapabilities } = useKibana().services.application; return Object.entries(kibanaCapabilities).reduce( - (availableOwners: string[], [featureId, kibananCapability]) => { + (availableOwners: string[], [featureId, kibanaCapability]) => { if (!featureId.endsWith('Cases')) { return availableOwners; } for (const cap of capabilities) { - const hasCapability = !!kibananCapability[`${cap}_cases`]; + const hasCapability = !!kibanaCapability[`${cap}_cases`]; if (!hasCapability) { return availableOwners; } diff --git a/x-pack/plugins/cases/public/components/filter_popover/index.tsx b/x-pack/plugins/cases/public/components/filter_popover/index.tsx index bd4f665bcd7fd4..0ef1d5a887c21b 100644 --- a/x-pack/plugins/cases/public/components/filter_popover/index.tsx +++ b/x-pack/plugins/cases/public/components/filter_popover/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { Dispatch, SetStateAction, useCallback, useState } from 'react'; +import React, { useCallback, useState } from 'react'; import { EuiFilterButton, EuiFilterSelectItem, @@ -19,7 +19,7 @@ import styled from 'styled-components'; interface FilterPopoverProps { buttonLabel: string; - onSelectedOptionsChanged: Dispatch<SetStateAction<string[]>>; + onSelectedOptionsChanged: (value: string[]) => void; options: string[]; optionsEmptyLabel?: string; selectedOptions: string[]; From 46a1125076330cc9f58df756fe3bfd4277900ecc Mon Sep 17 00:00:00 2001 From: Spencer <spencer@elastic.co> Date: Mon, 12 Sep 2022 07:51:00 -0700 Subject: [PATCH 070/144] Disable @elastic/unified-observability codeowners --- .github/CODEOWNERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cb9690ca3dc8d7..cebe65017c984c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -97,6 +97,7 @@ x-pack/examples/files_example @elastic/kibana-app-services # Unified Observability - on hold due to team capacity shortage # For now, if you're changing these pages, get a review from someone who understand the changes # /x-pack/plugins/observability/public/context @elastic/unified-observability +# /x-pack/test/observability_functional @elastic/unified-observability # Home/Overview/Landing Pages /x-pack/plugins/observability/public/pages/home @elastic/observability-design @@ -110,7 +111,7 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/observability/public/pages/cases @elastic/actionable-observability /x-pack/plugins/observability/public/pages/rules @elastic/actionable-observability /x-pack/plugins/observability/public/pages/rule_details @elastic/actionable-observability -/x-pack/test/observability_functional @elastic/actionable-observability @elastic/unified-observability +/x-pack/test/observability_functional @elastic/actionable-observability # Infra Monitoring /x-pack/plugins/infra/ @elastic/infra-monitoring-ui From 30af54d0a0fa5d5cab1758cd59d818192cbb0d4a Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 12 Sep 2022 08:56:22 -0600 Subject: [PATCH 071/144] skip failing test suite (#140507) --- .../apps/observability/pages/overview/alert_table.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts b/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts index d1b6a2ce625196..c4dea3334bc3cc 100644 --- a/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts +++ b/x-pack/test/observability_functional/apps/observability/pages/overview/alert_table.ts @@ -14,7 +14,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const PageObjects = getPageObjects(['header']); const esArchiver = getService('esArchiver'); - describe('Observability overview', function () { + // Failing: See https://github.com/elastic/kibana/issues/140507 + describe.skip('Observability overview', function () { this.tags('includeFirefox'); const observability = getService('observability'); From 2068b2eeadc3a0b4de0f5a940e446262069d1665 Mon Sep 17 00:00:00 2001 From: Robert Oskamp <robert.oskamp@elastic.co> Date: Mon, 12 Sep 2022 17:14:35 +0200 Subject: [PATCH 072/144] [ML] Functional tests - split anomaly detection test config (#140430) This PR splits the ML functional anomaly detection test configuration into smaller parts. --- .buildkite/ftr_configs.yml | 4 +- x-pack/plugins/ml/readme.md | 4 +- .../anomaly_charts_dashboard_embeddables.ts | 2 +- .../anomaly_embeddables_migration.ts | 2 +- .../anomaly_detection_integrations/config.ts | 20 +++++++++ .../constants.ts | 0 .../anomaly_detection_integrations/index.ts | 39 ++++++++++++++++++ .../lens_to_ml.ts | 0 .../lens_to_ml_with_wizard.ts | 0 .../advanced_job.ts | 0 .../categorization_job.ts | 0 .../config.ts | 2 +- .../custom_urls.ts | 0 .../date_nanos_job.ts | 0 .../index.ts | 7 ---- .../multi_metric_job.ts | 0 .../population_job.ts | 0 .../saved_search_job.ts | 0 .../single_metric_job.ts | 0 ...ingle_metric_job_without_datafeed_start.ts | 0 .../aggregated_scripted_job.ts | 0 .../annotations.ts | 0 .../anomaly_explorer.ts | 0 .../anomaly_detection_result_views/config.ts | 20 +++++++++ .../forecasts.ts | 0 .../anomaly_detection_result_views/index.ts | 41 +++++++++++++++++++ .../single_metric_viewer.ts | 0 .../apps/ml/short_tests/embeddables/index.ts | 16 -------- .../functional/apps/ml/short_tests/index.ts | 1 - 29 files changed, 129 insertions(+), 29 deletions(-) rename x-pack/test/functional/apps/ml/{short_tests/embeddables => anomaly_detection_integrations}/anomaly_charts_dashboard_embeddables.ts (98%) rename x-pack/test/functional/apps/ml/{short_tests/embeddables => anomaly_detection_integrations}/anomaly_embeddables_migration.ts (98%) create mode 100644 x-pack/test/functional/apps/ml/anomaly_detection_integrations/config.ts rename x-pack/test/functional/apps/ml/{short_tests/embeddables => anomaly_detection_integrations}/constants.ts (100%) create mode 100644 x-pack/test/functional/apps/ml/anomaly_detection_integrations/index.ts rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_integrations}/lens_to_ml.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_integrations}/lens_to_ml_with_wizard.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/advanced_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/categorization_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/config.ts (97%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/custom_urls.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/date_nanos_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/index.ts (82%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/multi_metric_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/population_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/saved_search_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/single_metric_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_jobs}/single_metric_job_without_datafeed_start.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_result_views}/aggregated_scripted_job.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_result_views}/annotations.ts (100%) rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_result_views}/anomaly_explorer.ts (100%) create mode 100644 x-pack/test/functional/apps/ml/anomaly_detection_result_views/config.ts rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_result_views}/forecasts.ts (100%) create mode 100644 x-pack/test/functional/apps/ml/anomaly_detection_result_views/index.ts rename x-pack/test/functional/apps/ml/{anomaly_detection => anomaly_detection_result_views}/single_metric_viewer.ts (100%) delete mode 100644 x-pack/test/functional/apps/ml/short_tests/embeddables/index.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index da3a104f9ca329..ffd9b63271d5f0 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -184,7 +184,9 @@ enabled: - x-pack/test/functional/apps/maps/group2/config.ts - x-pack/test/functional/apps/maps/group3/config.ts - x-pack/test/functional/apps/maps/group4/config.ts - - x-pack/test/functional/apps/ml/anomaly_detection/config.ts + - x-pack/test/functional/apps/ml/anomaly_detection_jobs/config.ts + - x-pack/test/functional/apps/ml/anomaly_detection_integrations/config.ts + - x-pack/test/functional/apps/ml/anomaly_detection_result_views/config.ts - x-pack/test/functional/apps/ml/data_frame_analytics/config.ts - x-pack/test/functional/apps/ml/data_visualizer/config.ts - x-pack/test/functional/apps/ml/permissions/config.ts diff --git a/x-pack/plugins/ml/readme.md b/x-pack/plugins/ml/readme.md index a29e976f12c462..b1b3ee8775dc21 100644 --- a/x-pack/plugins/ml/readme.md +++ b/x-pack/plugins/ml/readme.md @@ -117,7 +117,9 @@ With PATH_TO_CONFIG and other options as follows. Group | PATH_TO_CONFIG ----- | -------------- - anomaly detection | `test/functional/apps/ml/anomaly_detection/config.ts` + anomaly detection jobs | `test/functional/apps/ml/anomaly_detection_jobs/config.ts` + anomaly detection result views | `test/functional/apps/ml/anomaly_detection_result_views/config.ts` + anomaly detection integrations | `test/functional/apps/ml/anomaly_detection_integrations/config.ts` data frame analytics | `test/functional/apps/ml/data_frame_analytics/config.ts` data visualizer | `test/functional/apps/ml/data_visualizer/config.ts` permissions | `test/functional/apps/ml/permissions/config.ts` diff --git a/x-pack/test/functional/apps/ml/short_tests/embeddables/anomaly_charts_dashboard_embeddables.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_charts_dashboard_embeddables.ts similarity index 98% rename from x-pack/test/functional/apps/ml/short_tests/embeddables/anomaly_charts_dashboard_embeddables.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_charts_dashboard_embeddables.ts index ef674c1744a511..0cb95109df068d 100644 --- a/x-pack/test/functional/apps/ml/short_tests/embeddables/anomaly_charts_dashboard_embeddables.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_charts_dashboard_embeddables.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; import { JOB_CONFIG, DATAFEED_CONFIG, ML_EMBEDDABLE_TYPES } from './constants'; const testDataList = [ diff --git a/x-pack/test/functional/apps/ml/short_tests/embeddables/anomaly_embeddables_migration.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_embeddables_migration.ts similarity index 98% rename from x-pack/test/functional/apps/ml/short_tests/embeddables/anomaly_embeddables_migration.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_embeddables_migration.ts index 8f3c30a15e5433..7058286f3d5b3a 100644 --- a/x-pack/test/functional/apps/ml/short_tests/embeddables/anomaly_embeddables_migration.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_embeddables_migration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; import { JOB_CONFIG, DATAFEED_CONFIG, ML_EMBEDDABLE_TYPES } from './constants'; const testDataList = [ diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_integrations/config.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/config.ts new file mode 100644 index 00000000000000..363a72c4c0310c --- /dev/null +++ b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + junit: { + reportName: 'Chrome X-Pack UI Functional Tests - ML anomaly_detection_integrations', + }, + }; +} diff --git a/x-pack/test/functional/apps/ml/short_tests/embeddables/constants.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/constants.ts similarity index 100% rename from x-pack/test/functional/apps/ml/short_tests/embeddables/constants.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_integrations/constants.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_integrations/index.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/index.ts new file mode 100644 index 00000000000000..1859ab5a41d7fa --- /dev/null +++ b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/index.ts @@ -0,0 +1,39 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('machine learning - anomaly detection', function () { + this.tags(['skipFirefox']); + + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + // NOTE: Logout needs to happen before anything else to avoid flaky behavior + await ml.securityUI.logout(); + + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote'); + + await ml.testResources.resetKibanaTimeZone(); + }); + + loadTestFile(require.resolve('./anomaly_charts_dashboard_embeddables')); + loadTestFile(require.resolve('./anomaly_embeddables_migration')); + loadTestFile(require.resolve('./lens_to_ml')); + loadTestFile(require.resolve('./lens_to_ml_with_wizard')); + }); +} diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/lens_to_ml.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/lens_to_ml.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/lens_to_ml.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_integrations/lens_to_ml.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/lens_to_ml_with_wizard.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/lens_to_ml_with_wizard.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/lens_to_ml_with_wizard.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_integrations/lens_to_ml_with_wizard.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/advanced_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/advanced_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/advanced_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/advanced_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/categorization_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/categorization_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/categorization_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/categorization_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/config.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/config.ts similarity index 97% rename from x-pack/test/functional/apps/ml/anomaly_detection/config.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/config.ts index 9078782e36f0b5..c2bd1f7dbedfa4 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/config.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/config.ts @@ -14,7 +14,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...functionalConfig.getAll(), testFiles: [require.resolve('.')], junit: { - reportName: 'Chrome X-Pack UI Functional Tests - ML anomaly_detection', + reportName: 'Chrome X-Pack UI Functional Tests - ML anomaly_detection_jobs', }, }; } diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/custom_urls.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/custom_urls.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/custom_urls.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/custom_urls.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/date_nanos_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/date_nanos_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/index.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/index.ts similarity index 82% rename from x-pack/test/functional/apps/ml/anomaly_detection/index.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/index.ts index 35bfd4471233a9..e2f6901b75c315 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/index.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/index.ts @@ -40,15 +40,8 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./population_job')); loadTestFile(require.resolve('./saved_search_job')); loadTestFile(require.resolve('./advanced_job')); - loadTestFile(require.resolve('./single_metric_viewer')); - loadTestFile(require.resolve('./anomaly_explorer')); loadTestFile(require.resolve('./categorization_job')); loadTestFile(require.resolve('./date_nanos_job')); - loadTestFile(require.resolve('./annotations')); - loadTestFile(require.resolve('./aggregated_scripted_job')); loadTestFile(require.resolve('./custom_urls')); - loadTestFile(require.resolve('./forecasts')); - loadTestFile(require.resolve('./lens_to_ml')); - loadTestFile(require.resolve('./lens_to_ml_with_wizard')); }); } diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/multi_metric_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/multi_metric_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/multi_metric_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/multi_metric_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/population_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/population_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/population_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/population_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/saved_search_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/saved_search_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/saved_search_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/saved_search_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/single_metric_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/single_metric_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job_without_datafeed_start.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/single_metric_job_without_datafeed_start.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job_without_datafeed_start.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_jobs/single_metric_job_without_datafeed_start.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/aggregated_scripted_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/aggregated_scripted_job.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/aggregated_scripted_job.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_result_views/aggregated_scripted_job.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/annotations.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_result_views/annotations.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/anomaly_explorer.ts b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/anomaly_explorer.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/anomaly_explorer.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_result_views/anomaly_explorer.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_result_views/config.ts b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/config.ts new file mode 100644 index 00000000000000..c164a18f6df431 --- /dev/null +++ b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + junit: { + reportName: 'Chrome X-Pack UI Functional Tests - ML anomaly_detection_result_views', + }, + }; +} diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/forecasts.ts b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/forecasts.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/forecasts.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_result_views/forecasts.ts diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_result_views/index.ts b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/index.ts new file mode 100644 index 00000000000000..13f7ac9e97b09c --- /dev/null +++ b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/index.ts @@ -0,0 +1,41 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('machine learning - anomaly detection', function () { + this.tags(['skipFirefox']); + + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + // NOTE: Logout needs to happen before anything else to avoid flaky behavior + await ml.securityUI.logout(); + + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/ecommerce'); + + await ml.testResources.resetKibanaTimeZone(); + }); + + loadTestFile(require.resolve('./aggregated_scripted_job')); + loadTestFile(require.resolve('./annotations')); + loadTestFile(require.resolve('./anomaly_explorer')); + loadTestFile(require.resolve('./forecasts')); + loadTestFile(require.resolve('./single_metric_viewer')); + }); +} diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_viewer.ts b/x-pack/test/functional/apps/ml/anomaly_detection_result_views/single_metric_viewer.ts similarity index 100% rename from x-pack/test/functional/apps/ml/anomaly_detection/single_metric_viewer.ts rename to x-pack/test/functional/apps/ml/anomaly_detection_result_views/single_metric_viewer.ts diff --git a/x-pack/test/functional/apps/ml/short_tests/embeddables/index.ts b/x-pack/test/functional/apps/ml/short_tests/embeddables/index.ts deleted file mode 100644 index d786491e55a4ef..00000000000000 --- a/x-pack/test/functional/apps/ml/short_tests/embeddables/index.ts +++ /dev/null @@ -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 { FtrProviderContext } from '../../../../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('embeddables', function () { - this.tags(['skipFirefox']); - loadTestFile(require.resolve('./anomaly_charts_dashboard_embeddables')); - loadTestFile(require.resolve('./anomaly_embeddables_migration')); - }); -} diff --git a/x-pack/test/functional/apps/ml/short_tests/index.ts b/x-pack/test/functional/apps/ml/short_tests/index.ts index 3c4cbbc0677bea..f96d2b91ee0ef7 100644 --- a/x-pack/test/functional/apps/ml/short_tests/index.ts +++ b/x-pack/test/functional/apps/ml/short_tests/index.ts @@ -33,6 +33,5 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./model_management')); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./settings')); - loadTestFile(require.resolve('./embeddables')); }); } From 0c448be50a492f796d183c004c531844d5d1cc75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20=C3=81brah=C3=A1m?= <abrahamgergo@gmail.com> Date: Mon, 12 Sep 2022 17:31:42 +0200 Subject: [PATCH 073/144] [Security Solution][Endpoint][Response Actions] Keep Response console Arrow button disabled for whitespace characters (#140429) --- .../command_input/command_input.test.tsx | 25 ++++++++++++++++--- .../command_input/command_input.tsx | 7 ++---- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx index 4cb233ee0c4808..25d7409036d8c8 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.test.tsx @@ -42,6 +42,10 @@ describe('When entering data into the Console input', () => { return renderResult.getByTestId('test-footer').textContent; }; + const typeKeyboardKey = (key: string) => { + enterCommand(key, { inputOnly: true, useKeyboard: true }); + }; + beforeEach(() => { const testSetup = getConsoleTestSetup(); @@ -124,6 +128,23 @@ describe('When entering data into the Console input', () => { expect(arrowButton).toBeDisabled(); }); + it('should show the arrow button as disabled if input has only whitespace entered and it is left to the cursor', () => { + render(); + enterCommand(' ', { inputOnly: true }); + + const arrowButton = renderResult.getByTestId('test-inputTextSubmitButton'); + expect(arrowButton).toBeDisabled(); + }); + + it('should show the arrow button as disabled if input has only whitespace entered and it is right to the cursor', () => { + render(); + enterCommand(' ', { inputOnly: true }); + typeKeyboardKey('{ArrowLeft}'); + + const arrowButton = renderResult.getByTestId('test-inputTextSubmitButton'); + expect(arrowButton).toBeDisabled(); + }); + it('should execute correct command if arrow button is clicked', () => { render(); enterCommand('isolate', { inputOnly: true }); @@ -200,10 +221,6 @@ describe('When entering data into the Console input', () => { return renderResult.getByTestId('test-cmdInput-rightOfCursor').textContent; }; - const typeKeyboardKey = (key: string) => { - enterCommand(key, { inputOnly: true, useKeyboard: true }); - }; - beforeEach(() => { render(); enterCommand('isolate', { inputOnly: true }); diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx index 92f5c9ff33b0eb..0829c1af193edb 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/command_input/command_input.tsx @@ -82,7 +82,7 @@ export interface CommandInputProps extends CommonProps { export const CommandInput = memo<CommandInputProps>(({ prompt = '', focusRef, ...commonProps }) => { useInputHints(); const dispatch = useConsoleStateDispatch(); - const { rightOfCursor, textEntered } = useWithInputTextEntered(); + const { rightOfCursor, textEntered, fullTextEntered } = useWithInputTextEntered(); const visibleState = useWithInputVisibleState(); const [isKeyInputBeingCaptured, setIsKeyInputBeingCaptured] = useState(false); const getTestId = useTestIdGenerator(useDataTestSubj()); @@ -117,10 +117,7 @@ export const CommandInput = memo<CommandInputProps>(({ prompt = '', focusRef, .. }); }, [isKeyInputBeingCaptured, visibleState]); - const disableArrowButton = useMemo( - () => textEntered.length === 0 && rightOfCursor.text.length === 0, - [rightOfCursor.text.length, textEntered.length] - ); + const disableArrowButton = useMemo(() => fullTextEntered.trim().length === 0, [fullTextEntered]); const handleSubmitButton = useCallback<MouseEventHandler>( (ev) => { From a8012aa51c7b1c53b2b9428785b7cfb973f62485 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet <nicolas.chaulet@elastic.co> Date: Mon, 12 Sep 2022 11:41:03 -0400 Subject: [PATCH 074/144] [Fleet] Show beta badge for datastream in package policy editor (#140305) --- .../package_to_package_policy.test.ts.snap | 23 ++++++++++++ .../services/package_to_package_policy.ts | 10 ++++-- .../plugins/fleet/common/types/models/epm.ts | 2 +- .../common/types/models/package_policy.ts | 3 +- .../package_policy_input_stream.tsx | 36 +++++++++++++------ .../single_page_layout/index.test.tsx | 2 ++ .../sections/epm/components/package_card.tsx | 5 ++- .../sections/epm/screens/detail/index.tsx | 4 +-- .../plugins/fleet/public/components/index.ts | 1 + .../epm => }/components/release_badge.tsx | 4 +-- ...plified_package_policy_helper.test.ts.snap | 5 +++ .../server/services/package_policy.test.ts | 1 + .../server/types/models/package_policy.ts | 3 ++ .../uptime/rest/sample_data/test_policy.ts | 12 +++++++ 14 files changed, 88 insertions(+), 23 deletions(-) rename x-pack/plugins/fleet/public/{applications/integrations/sections/epm => }/components/release_badge.tsx (92%) diff --git a/x-pack/plugins/fleet/common/services/__snapshots__/package_to_package_policy.test.ts.snap b/x-pack/plugins/fleet/common/services/__snapshots__/package_to_package_policy.test.ts.snap index 3235ebbd9a8f95..1edc3d850f7756 100644 --- a/x-pack/plugins/fleet/common/services/__snapshots__/package_to_package_policy.test.ts.snap +++ b/x-pack/plugins/fleet/common/services/__snapshots__/package_to_package_policy.test.ts.snap @@ -15,6 +15,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "cost_explorer_config.group_by_dimension_keys": Object { "type": "text", @@ -53,6 +54,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "beta", "vars": Object { "api_timeout": Object { "type": "text", @@ -85,6 +87,7 @@ Object { "type": "logs", }, "enabled": false, + "release": "beta", "vars": Object { "interval": Object { "type": "text", @@ -131,6 +134,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "beta", "vars": Object { "api_timeout": Object { "type": "text", @@ -163,6 +167,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -209,6 +214,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -243,6 +249,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -277,6 +284,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "beta", "vars": Object { "api_timeout": Object { "type": "text", @@ -309,6 +317,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -343,6 +352,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "beta", "vars": Object { "api_timeout": Object { "type": "text", @@ -375,6 +385,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -409,6 +420,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -443,6 +455,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -471,6 +484,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -505,6 +519,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "beta", "vars": Object { "api_timeout": Object { "type": "text", @@ -537,6 +552,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -558,6 +574,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -586,6 +603,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -620,6 +638,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -648,6 +667,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -676,6 +696,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", @@ -704,6 +725,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "beta", "vars": Object { "api_timeout": Object { "type": "text", @@ -736,6 +758,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "beta", "vars": Object { "latency": Object { "type": "text", diff --git a/x-pack/plugins/fleet/common/services/package_to_package_policy.ts b/x-pack/plugins/fleet/common/services/package_to_package_policy.ts index cea02893e849d3..6944df380d3dd2 100644 --- a/x-pack/plugins/fleet/common/services/package_to_package_policy.ts +++ b/x-pack/plugins/fleet/common/services/package_to_package_policy.ts @@ -19,12 +19,16 @@ import type { import { doesPackageHaveIntegrations } from '.'; +type PackagePolicyStream = RegistryStream & { release?: 'beta' | 'experimental' | 'ga' } & { + data_stream: { type: string; dataset: string }; +}; + export const getStreamsForInputType = ( inputType: string, packageInfo: PackageInfo, dataStreamPaths: string[] = [] -): Array<RegistryStream & { data_stream: { type: string; dataset: string } }> => { - const streams: Array<RegistryStream & { data_stream: { type: string; dataset: string } }> = []; +): PackagePolicyStream[] => { + const streams: PackagePolicyStream[] = []; const dataStreams = packageInfo.data_streams || []; const dataStreamsToSearch = dataStreamPaths.length ? dataStreams.filter((dataStream) => dataStreamPaths.includes(dataStream.path)) @@ -39,6 +43,7 @@ export const getStreamsForInputType = ( type: dataStream.type, dataset: dataStream.dataset, }, + release: dataStream.release, }); } }); @@ -102,6 +107,7 @@ export const packageToPackagePolicyInputs = ( const stream: NewPackagePolicyInputStream = { enabled: packageStream.enabled === false ? false : true, data_stream: packageStream.data_stream, + release: packageStream.release, }; if (packageStream.vars && packageStream.vars.length) { stream.vars = packageStream.vars.reduce(varsReducer, {}); diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 519222b4e3c101..977d9d2be7d618 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -315,7 +315,7 @@ export interface RegistryDataStream { [RegistryDataStreamKeys.hidden]?: boolean; [RegistryDataStreamKeys.dataset]: string; [RegistryDataStreamKeys.title]: string; - [RegistryDataStreamKeys.release]: string; + [RegistryDataStreamKeys.release]: RegistryRelease; [RegistryDataStreamKeys.streams]?: RegistryStream[]; [RegistryDataStreamKeys.package]: string; [RegistryDataStreamKeys.path]: string; diff --git a/x-pack/plugins/fleet/common/types/models/package_policy.ts b/x-pack/plugins/fleet/common/types/models/package_policy.ts index 4673fefbd9536f..629250c243cea8 100644 --- a/x-pack/plugins/fleet/common/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/common/types/models/package_policy.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { ExperimentalDataStreamFeature } from './epm'; +import type { RegistryRelease, ExperimentalDataStreamFeature } from './epm'; export interface PackagePolicyPackage { name: string; @@ -35,6 +35,7 @@ export interface NewPackagePolicyInputStream { }; }; }; + release?: RegistryRelease; vars?: PackagePolicyConfigRecord; config?: PackagePolicyConfigRecord; } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx index 166078eb01dd24..e1993082b37bf7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/package_policy_input_stream.tsx @@ -30,6 +30,7 @@ import type { RegistryStream, RegistryVarsEntry, } from '../../../../../../types'; +import { InlineReleaseBadge } from '../../../../../../components'; import type { PackagePolicyConfigValidationResults } from '../../../services'; import { isAdvancedVar, validationHasErrors } from '../../../services'; import { PackagePolicyEditorDatastreamPipelines } from '../../datastream_pipelines'; @@ -123,17 +124,30 @@ export const PackagePolicyInputStreamConfig: React.FunctionComponent<{ <EuiFlexGroup gutterSize="none" alignItems="flexStart"> <EuiFlexItem grow={1} /> <EuiFlexItem grow={5}> - <EuiSwitch - label={packageInputStream.title} - disabled={packagePolicyInputStream.keep_enabled} - checked={packagePolicyInputStream.enabled} - onChange={(e) => { - const enabled = e.target.checked; - updatePackagePolicyInputStream({ - enabled, - }); - }} - /> + <EuiFlexGroup + gutterSize="none" + alignItems="flexStart" + justifyContent="spaceBetween" + > + <EuiFlexItem grow={false}> + <EuiSwitch + label={packageInputStream.title} + disabled={packagePolicyInputStream.keep_enabled} + checked={packagePolicyInputStream.enabled} + onChange={(e) => { + const enabled = e.target.checked; + updatePackagePolicyInputStream({ + enabled, + }); + }} + /> + </EuiFlexItem> + {packagePolicyInputStream.release && packagePolicyInputStream.release !== 'ga' ? ( + <EuiFlexItem grow={false}> + <InlineReleaseBadge release={packagePolicyInputStream.release} /> + </EuiFlexItem> + ) : null} + </EuiFlexGroup> {packageInputStream.description ? ( <Fragment> <EuiSpacer size="s" /> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx index 88061897abf767..c359bc9679e44a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/index.test.tsx @@ -239,6 +239,7 @@ describe('when on the package policy create page', () => { dataset: 'nginx.access', type: 'logs', }, + release: 'experimental', enabled: true, vars: { paths: { @@ -536,6 +537,7 @@ describe('when on the package policy create page', () => { streams: [ { ...newPackagePolicy.inputs[0].streams[0], + release: 'experimental', vars: { paths: { type: 'text', diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_card.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_card.tsx index fa96da7ea6acec..a37fdcf5533c86 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_card.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_card.tsx @@ -16,11 +16,10 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { CardIcon } from '../../../../../components/package_icon'; import type { IntegrationCardItem } from '../../../../../../common/types/models/epm'; +import { InlineReleaseBadge } from '../../../components'; import { useStartServices } from '../../../hooks'; import { INTEGRATIONS_BASE_PATH, INTEGRATIONS_PLUGIN_ID } from '../../../constants'; -import { CardReleaseBadge } from './release_badge'; - export type PackageCardProps = IntegrationCardItem; // Min-height is roughly 3 lines of content. @@ -50,7 +49,7 @@ export function PackageCard({ <EuiFlexItem grow={false}> <EuiSpacer size="xs" /> <span> - <CardReleaseBadge release={release} /> + <InlineReleaseBadge release={release} /> </span> </EuiFlexItem> ); diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx index d3e97110b57ad0..dfe1c6001cedef 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/index.tsx @@ -41,12 +41,10 @@ import { useGetPackageInfoByKey, useLink, useAgentPolicyContext } from '../../.. import { pkgKeyFromPackageInfo } from '../../../../services'; import type { DetailViewPanelName, PackageInfo } from '../../../../types'; import { InstallStatus } from '../../../../types'; -import { Error, Loading } from '../../../../components'; +import { Error, Loading, HeaderReleaseBadge } from '../../../../components'; import type { WithHeaderLayoutProps } from '../../../../layouts'; import { WithHeaderLayout } from '../../../../layouts'; -import { HeaderReleaseBadge } from '../../components/release_badge'; - import { useIsFirstTimeAgentUser } from './hooks'; import { getInstallPkgRouteOptions } from './utils'; import { diff --git a/x-pack/plugins/fleet/public/components/index.ts b/x-pack/plugins/fleet/public/components/index.ts index e1a1e608871720..4e9d9f0f021b0a 100644 --- a/x-pack/plugins/fleet/public/components/index.ts +++ b/x-pack/plugins/fleet/public/components/index.ts @@ -25,3 +25,4 @@ export * from './link_and_revision'; export * from './agent_enrollment_flyout'; export * from './platform_selector'; export { ConfirmForceInstallModal } from './confirm_force_install_modal'; +export { HeaderReleaseBadge, InlineReleaseBadge } from './release_badge'; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/release_badge.tsx b/x-pack/plugins/fleet/public/components/release_badge.tsx similarity index 92% rename from x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/release_badge.tsx rename to x-pack/plugins/fleet/public/components/release_badge.tsx index 3032b61d563337..3252ea21ee2dff 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/release_badge.tsx +++ b/x-pack/plugins/fleet/public/components/release_badge.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { EuiBadge, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import type { PackageInfo, RegistryRelease } from '../../../types'; +import type { PackageInfo, RegistryRelease } from '../types'; const RELEASE_BADGE_LABEL: { [key in Exclude<RegistryRelease, 'ga'>]: string } = { beta: i18n.translate('xpack.fleet.epm.releaseBadge.betaLabel', { @@ -43,7 +43,7 @@ export const HeaderReleaseBadge: React.FC<{ release: NonNullable<PackageInfo['re ); }; -export const CardReleaseBadge: React.FC<{ release: NonNullable<PackageInfo['release']> }> = ({ +export const InlineReleaseBadge: React.FC<{ release: NonNullable<PackageInfo['release']> }> = ({ release, }) => { if (release === 'ga') return null; diff --git a/x-pack/plugins/fleet/server/services/package_policies/__snapshots__/simplified_package_policy_helper.test.ts.snap b/x-pack/plugins/fleet/server/services/package_policies/__snapshots__/simplified_package_policy_helper.test.ts.snap index 200eed919407ed..35c8b917853f9e 100644 --- a/x-pack/plugins/fleet/server/services/package_policies/__snapshots__/simplified_package_policy_helper.test.ts.snap +++ b/x-pack/plugins/fleet/server/services/package_policies/__snapshots__/simplified_package_policy_helper.test.ts.snap @@ -15,6 +15,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "ga", "vars": Object { "ignore_older": Object { "type": "text", @@ -48,6 +49,7 @@ Object { "type": "logs", }, "enabled": true, + "release": "ga", "vars": Object { "ignore_older": Object { "type": "text", @@ -89,6 +91,7 @@ Object { "type": "logs", }, "enabled": false, + "release": "ga", "vars": Object { "interval": Object { "type": "text", @@ -121,6 +124,7 @@ Object { "type": "logs", }, "enabled": false, + "release": "ga", "vars": Object { "interval": Object { "type": "text", @@ -203,6 +207,7 @@ Object { "type": "metrics", }, "enabled": true, + "release": "ga", "vars": Object { "period": Object { "type": "text", diff --git a/x-pack/plugins/fleet/server/services/package_policy.test.ts b/x-pack/plugins/fleet/server/services/package_policy.test.ts index 9804f0d1478684..59e4104c624788 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.test.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.test.ts @@ -3502,6 +3502,7 @@ describe('_applyIndexPrivileges()', () => { type: '', dataset: '', title: '', + // @ts-ignore-error release: '', package: '', path: '', diff --git a/x-pack/plugins/fleet/server/types/models/package_policy.ts b/x-pack/plugins/fleet/server/types/models/package_policy.ts index bddce3acbc847e..9763d09e205558 100644 --- a/x-pack/plugins/fleet/server/types/models/package_policy.ts +++ b/x-pack/plugins/fleet/server/types/models/package_policy.ts @@ -32,6 +32,9 @@ const PackagePolicyStreamsSchema = { id: schema.maybe(schema.string()), // BWC < 7.11 enabled: schema.boolean(), keep_enabled: schema.maybe(schema.boolean()), + release: schema.maybe( + schema.oneOf([schema.literal('ga'), schema.literal('beta'), schema.literal('experimental')]) + ), data_stream: schema.object({ dataset: schema.string(), type: schema.string(), diff --git a/x-pack/test/api_integration/apis/uptime/rest/sample_data/test_policy.ts b/x-pack/test/api_integration/apis/uptime/rest/sample_data/test_policy.ts index 5e6795ba86ef06..f24c839ddb296a 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/sample_data/test_policy.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/sample_data/test_policy.ts @@ -30,6 +30,7 @@ export const getTestSyntheticsPolicy = ( { enabled: true, data_stream: { type: 'synthetics', dataset: 'http' }, + release: 'experimental', vars: { __ui: { value: @@ -129,6 +130,7 @@ export const getTestSyntheticsPolicy = ( streams: [ { enabled: false, + release: 'experimental', data_stream: { type: 'synthetics', dataset: 'tcp' }, vars: { __ui: { type: 'yaml' }, @@ -167,6 +169,7 @@ export const getTestSyntheticsPolicy = ( streams: [ { enabled: false, + release: 'experimental', data_stream: { type: 'synthetics', dataset: 'icmp' }, vars: { __ui: { type: 'yaml' }, @@ -196,6 +199,7 @@ export const getTestSyntheticsPolicy = ( streams: [ { enabled: true, + release: 'beta', data_stream: { type: 'synthetics', dataset: 'browser' }, vars: { __ui: { type: 'yaml' }, @@ -253,6 +257,7 @@ export const getTestSyntheticsPolicy = ( { enabled: true, data_stream: { type: 'synthetics', dataset: 'browser.network' }, + release: 'beta', id: 'synthetics/browser-browser.network-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default', compiled_stream: { processors: [ @@ -264,6 +269,7 @@ export const getTestSyntheticsPolicy = ( { enabled: true, data_stream: { type: 'synthetics', dataset: 'browser.screenshot' }, + release: 'beta', id: 'synthetics/browser-browser.screenshot-2bfd7da0-22ed-11ed-8c6b-09a2d21dfbc3-27337270-22ed-11ed-8c6b-09a2d21dfbc3-default', compiled_stream: { processors: [ @@ -317,6 +323,7 @@ export const getTestProjectSyntheticsPolicy = ( { enabled: false, data_stream: { type: 'synthetics', dataset: 'http' }, + release: 'experimental', vars: { __ui: { type: 'yaml' }, enabled: { value: true, type: 'bool' }, @@ -364,6 +371,7 @@ export const getTestProjectSyntheticsPolicy = ( { enabled: false, data_stream: { type: 'synthetics', dataset: 'tcp' }, + release: 'experimental', vars: { __ui: { type: 'yaml' }, enabled: { value: true, type: 'bool' }, @@ -401,6 +409,7 @@ export const getTestProjectSyntheticsPolicy = ( streams: [ { enabled: false, + release: 'experimental', data_stream: { type: 'synthetics', dataset: 'icmp' }, vars: { __ui: { type: 'yaml' }, @@ -431,6 +440,7 @@ export const getTestProjectSyntheticsPolicy = ( { enabled: true, data_stream: { type: 'synthetics', dataset: 'browser' }, + release: 'beta', vars: { __ui: { value: @@ -522,6 +532,7 @@ export const getTestProjectSyntheticsPolicy = ( }, { enabled: true, + release: 'beta', data_stream: { type: 'synthetics', dataset: 'browser.network' }, id: 'synthetics/browser-browser.network-4b6abc6c-118b-4d93-a489-1135500d09f1-test-suite-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3', compiled_stream: { @@ -533,6 +544,7 @@ export const getTestProjectSyntheticsPolicy = ( }, { enabled: true, + release: 'beta', data_stream: { type: 'synthetics', dataset: 'browser.screenshot' }, id: 'synthetics/browser-browser.screenshot-4b6abc6c-118b-4d93-a489-1135500d09f1-test-suite-default-d70a46e0-22ea-11ed-8c6b-09a2d21dfbc3', compiled_stream: { From b474a454f626d088814dbab572c646f0c9c7d4b8 Mon Sep 17 00:00:00 2001 From: Kurt <kc13greiner@users.noreply.github.com> Date: Mon, 12 Sep 2022 11:41:20 -0400 Subject: [PATCH 075/144] =?UTF-8?q?Adding=20info=20logging=20to=20display?= =?UTF-8?q?=20the=20hashed=20encryptionKey=20&=20adding=20test=E2=80=A6=20?= =?UTF-8?q?(#139874)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adding info logging to display the hashed encryptionKey & adding test cases * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * Fixing test logger * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * Adding config path for message * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../server/plugin.test.ts | 18 +++++++++++++----- .../encrypted_saved_objects/server/plugin.ts | 9 +++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts b/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts index 970f3baed7ab1a..527e4bcd82535b 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/plugin.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { coreMock } from '@kbn/core/server/mocks'; +import { coreMock, loggingSystemMock } from '@kbn/core/server/mocks'; import { securityMock } from '@kbn/security-plugin/server/mocks'; import { ConfigSchema } from './config'; @@ -28,11 +28,12 @@ describe('EncryptedSavedObjects Plugin', () => { }); it('exposes proper contract when encryption key is set', () => { - const plugin = new EncryptedSavedObjectsPlugin( - coreMock.createPluginInitializerContext( - ConfigSchema.validate({ encryptionKey: 'z'.repeat(32) }, { dist: true }) - ) + const mockInitializerContext = coreMock.createPluginInitializerContext( + ConfigSchema.validate({ encryptionKey: 'z'.repeat(32) }, { dist: true }) ); + + const plugin = new EncryptedSavedObjectsPlugin(mockInitializerContext); + expect(plugin.setup(coreMock.createSetup(), { security: securityMock.createSetup() })) .toMatchInlineSnapshot(` Object { @@ -41,6 +42,13 @@ describe('EncryptedSavedObjects Plugin', () => { "registerType": [Function], } `); + + const infoLogs = loggingSystemMock.collect(mockInitializerContext.logger).info; + + expect(infoLogs.length).toBe(1); + expect(infoLogs[0]).toEqual([ + `Hashed 'xpack.encryptedSavedObjects.encryptionKey' for this instance: WLbjNGKEm7aA4NfJHYyW88jHUkHtyF7ENHcF0obYGBU=`, + ]); }); }); diff --git a/x-pack/plugins/encrypted_saved_objects/server/plugin.ts b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts index 5ba387128ef7e0..92a663fab64d40 100644 --- a/x-pack/plugins/encrypted_saved_objects/server/plugin.ts +++ b/x-pack/plugins/encrypted_saved_objects/server/plugin.ts @@ -6,6 +6,7 @@ */ import nodeCrypto from '@elastic/node-crypto'; +import { createHash } from 'crypto'; import type { CoreSetup, Logger, Plugin, PluginInitializerContext } from '@kbn/core/server'; import type { SecurityPluginSetup } from '@kbn/security-plugin/server'; @@ -63,6 +64,14 @@ export class EncryptedSavedObjectsPlugin 'Saved objects encryption key is not set. This will severely limit Kibana functionality. ' + 'Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command.' ); + } else { + const hashedEncryptionKey = createHash('sha3-256') + .update(config.encryptionKey) + .digest('base64'); + + this.logger.info( + `Hashed 'xpack.encryptedSavedObjects.encryptionKey' for this instance: ${hashedEncryptionKey}` + ); } const primaryCrypto = config.encryptionKey From fecb6b30be95a7db9f766800bedd71a72662f61d Mon Sep 17 00:00:00 2001 From: Nathan Reese <reese.nathan@elastic.co> Date: Mon, 12 Sep 2022 09:52:45 -0600 Subject: [PATCH 076/144] [Maps] fix percentile aggregation not working with vector tiles (#140318) * [Maps] fix percentile aggregation not working with vector tiles * better test names * fix jest test * review feedback * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fields/agg/percentile_agg_field.test.ts | 97 +++++++++++++++---- .../fields/agg/percentile_agg_field.ts | 7 ++ 2 files changed, 84 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.test.ts b/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.test.ts index 3b6eff33130776..a00a5d1fcd1866 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.test.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.test.ts @@ -46,15 +46,11 @@ const mockEsDocField = { }, }; -const defaultParams = { - source: mockEsAggSource, - origin: FIELD_ORIGIN.SOURCE, -}; - describe('percentile agg field', () => { test('should include percentile in name', () => { const field = new PercentileAggField({ - ...defaultParams, + source: mockEsAggSource, + origin: FIELD_ORIGIN.SOURCE, esDocField: mockEsDocField as ESDocField, percentile: 80, }); @@ -63,7 +59,8 @@ describe('percentile agg field', () => { test('should create percentile dsl', () => { const field = new PercentileAggField({ - ...defaultParams, + source: mockEsAggSource, + origin: FIELD_ORIGIN.SOURCE, esDocField: mockEsDocField as ESDocField, percentile: 80, }); @@ -73,24 +70,84 @@ describe('percentile agg field', () => { }); }); - test('label', async () => { - const field = new PercentileAggField({ - ...defaultParams, - esDocField: mockEsDocField as ESDocField, - percentile: 80, + describe('getLabel', () => { + test('should return percentile in label', async () => { + const field = new PercentileAggField({ + source: mockEsAggSource, + origin: FIELD_ORIGIN.SOURCE, + esDocField: mockEsDocField as ESDocField, + percentile: 80, + }); + + expect(await field.getLabel()).toEqual('80th agg_label'); }); - expect(await field.getLabel()).toEqual('80th agg_label'); + test('should return median for 50th percentile', async () => { + const field = new PercentileAggField({ + source: mockEsAggSource, + origin: FIELD_ORIGIN.SOURCE, + label: '', + esDocField: mockEsDocField as ESDocField, + percentile: 50, + }); + + expect(await field.getLabel()).toEqual('median foobar'); + }); }); - test('label (median)', async () => { - const field = new PercentileAggField({ - ...defaultParams, - label: '', - esDocField: mockEsDocField as ESDocField, - percentile: 50, + describe('getMbFieldName', () => { + test('should return field name when source is not MVT', () => { + const field = new PercentileAggField({ + origin: FIELD_ORIGIN.SOURCE, + source: { + getAggKey: (aggType: AGG_TYPE, fieldName: string) => { + return 'agg_key'; + }, + isMvt: () => { + return false; + }, + } as unknown as IESAggSource, + esDocField: mockEsDocField as ESDocField, + percentile: 80.5, + }); + + expect(field.getMbFieldName()).toEqual('agg_key_80.5'); + }); + + test('should return field name and percentile when source is MVT', () => { + const field = new PercentileAggField({ + origin: FIELD_ORIGIN.SOURCE, + source: { + getAggKey: (aggType: AGG_TYPE, fieldName: string) => { + return 'agg_key'; + }, + isMvt: () => { + return true; + }, + } as unknown as IESAggSource, + esDocField: mockEsDocField as ESDocField, + percentile: 80.5, + }); + + expect(field.getMbFieldName()).toEqual('agg_key_80.5.values.80.5'); }); - expect(await field.getLabel()).toEqual('median foobar'); + test('should return field name and percentile with single decimal place when source is MVT and percentile is interger', () => { + const field = new PercentileAggField({ + origin: FIELD_ORIGIN.SOURCE, + source: { + getAggKey: (aggType: AGG_TYPE, fieldName: string) => { + return 'agg_key'; + }, + isMvt: () => { + return true; + }, + } as unknown as IESAggSource, + esDocField: mockEsDocField as ESDocField, + percentile: 80, + }); + + expect(field.getMbFieldName()).toEqual('agg_key_80.values.80.0'); + }); }); }); diff --git a/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts index 57dcd5631918c1..c1e076eacd6202 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts @@ -40,6 +40,13 @@ export class PercentileAggField extends AggField implements IESAggField { return true; } + getMbFieldName(): string { + return this._source.isMvt() + ? this.getName() + + `.values.${this._percentile}${Number.isInteger(this._percentile) ? '.0' : ''}` + : this.getName(); + } + canValueBeFormatted(): boolean { return true; } From c151f3212384c97a7fc68412f457b27a0dd5f345 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm <matthias.wilhelm@elastic.co> Date: Mon, 12 Sep 2022 17:54:57 +0200 Subject: [PATCH 077/144] [Discover] Refactor text based query language state transformation (#140169) * Extract useTextBasedQueryLanguage hook * Add unit tests * Add comments * Refactor data view list handling --- .../discover/public/__mocks__/data_views.ts | 5 + .../discover/public/__mocks__/services.ts | 2 + .../layout/discover_layout.test.tsx | 7 +- .../main/components/layout/types.ts | 7 +- .../sidebar/discover_sidebar.test.tsx | 10 +- .../discover_sidebar_responsive.test.tsx | 9 +- .../sidebar/discover_sidebar_responsive.tsx | 5 +- .../main/discover_main_app.test.tsx | 5 +- .../application/main/discover_main_app.tsx | 10 +- .../application/main/discover_main_route.tsx | 11 +- .../main/hooks/use_discover_state.test.ts | 17 +- .../main/hooks/use_discover_state.ts | 117 +++----- .../main/hooks/use_saved_search.test.ts | 4 + .../main/hooks/use_saved_search.ts | 2 + .../main/hooks/use_saved_search_messages.ts | 5 +- .../use_test_based_query_language.test.ts | 249 ++++++++++++++++++ .../hooks/use_text_based_query_language.ts | 113 ++++++++ .../application/main/utils/fetch_all.test.ts | 6 +- .../application/main/utils/fetch_all.ts | 5 +- .../main/utils/resolve_data_view.test.ts | 6 +- .../main/utils/resolve_data_view.ts | 18 +- 21 files changed, 460 insertions(+), 153 deletions(-) create mode 100644 src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts create mode 100644 src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts diff --git a/src/plugins/discover/public/__mocks__/data_views.ts b/src/plugins/discover/public/__mocks__/data_views.ts index e16f16b7a87e9a..f1509b323e098d 100644 --- a/src/plugins/discover/public/__mocks__/data_views.ts +++ b/src/plugins/discover/public/__mocks__/data_views.ts @@ -8,6 +8,8 @@ import { DataViewsContract } from '@kbn/data-views-plugin/public'; import { dataViewMock } from './data_view'; +import { dataViewComplexMock } from './data_view_complex'; +import { dataViewWithTimefieldMock } from './data_view_with_timefield'; export const dataViewsMock = { getCache: async () => { @@ -21,4 +23,7 @@ export const dataViewsMock = { } }, updateSavedObject: jest.fn(), + getIdsWithTitle: jest.fn(() => { + return Promise.resolve([dataViewMock, dataViewComplexMock, dataViewWithTimefieldMock]); + }), } as unknown as jest.Mocked<DataViewsContract>; diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index a6c95405ccd5da..9a466f6971c0bf 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -25,6 +25,7 @@ import { TopNavMenu } from '@kbn/navigation-plugin/public'; import { FORMATS_UI_SETTINGS } from '@kbn/field-formats-plugin/common'; import { LocalStorageMock } from './local_storage_mock'; import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; +import { dataViewsMock } from './data_views'; const dataPlugin = dataPluginMock.createStartContract(); const expressionsPlugin = expressionsPluginMock.createStartContract(); @@ -114,4 +115,5 @@ export const discoverServiceMock = { }, expressions: expressionsPlugin, savedObjectsTagging: {}, + dataViews: dataViewsMock, } as unknown as DiscoverServices; diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index aae6e0430a7d8a..75bbedc0b8513e 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -16,8 +16,7 @@ import { esHits } from '../../../../__mocks__/es_hits'; import { dataViewMock } from '../../../../__mocks__/data_view'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; import { createSearchSourceMock } from '@kbn/data-plugin/common/search/search_source/mocks'; -import type { DataView, DataViewAttributes } from '@kbn/data-views-plugin/public'; -import { SavedObject } from '@kbn/core/types'; +import type { DataView } from '@kbn/data-views-plugin/public'; import { dataViewWithTimefieldMock } from '../../../../__mocks__/data_view_with_timefield'; import { GetStateReturn } from '../../services/discover_state'; import { DiscoverLayoutProps } from './types'; @@ -59,9 +58,7 @@ function mountComponent( return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' }; }; - const dataViewList = [dataView].map((ip) => { - return { ...ip, ...{ attributes: { title: ip.title } } }; - }) as unknown as Array<SavedObject<DataViewAttributes>>; + const dataViewList = [dataView]; const main$ = new BehaviorSubject({ fetchStatus: FetchStatus.COMPLETE, diff --git a/src/plugins/discover/public/application/main/components/layout/types.ts b/src/plugins/discover/public/application/main/components/layout/types.ts index e254dd8774a37a..828b3bac4aa65d 100644 --- a/src/plugins/discover/public/application/main/components/layout/types.ts +++ b/src/plugins/discover/public/application/main/components/layout/types.ts @@ -7,9 +7,8 @@ */ import type { Query, TimeRange, AggregateQuery } from '@kbn/es-query'; -import type { SavedObject } from '@kbn/data-plugin/public'; -import type { DataView, DataViewAttributes } from '@kbn/data-views-plugin/public'; -import { ISearchSource } from '@kbn/data-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { DataViewListItem, ISearchSource } from '@kbn/data-plugin/public'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; import { DataTableRecord } from '../../../../types'; @@ -18,7 +17,7 @@ import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search'; export interface DiscoverLayoutProps { dataView: DataView; - dataViewList: Array<SavedObject<DataViewAttributes>>; + dataViewList: DataViewListItem[]; inspectorAdapters: { requests: RequestAdapter }; navigateTo: (url: string) => void; onChangeDataView: (id: string) => void; diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx index b5b612a9ed2762..c6a8eb20143ea6 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx @@ -12,8 +12,8 @@ import { getDataTableRecords } from '../../../../__fixtures__/real_hits'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import React from 'react'; import { DiscoverSidebarProps } from './discover_sidebar'; -import { DataViewAttributes } from '@kbn/data-views-plugin/public'; -import { SavedObject } from '@kbn/core/types'; +import { DataViewListItem } from '@kbn/data-views-plugin/public'; + import { getDefaultFieldFilter } from './lib/field_filter'; import { DiscoverSidebarComponent as DiscoverSidebar } from './discover_sidebar'; import { discoverServiceMock as mockDiscoverServices } from '../../../../__mocks__/services'; @@ -39,9 +39,9 @@ function getCompProps(): DiscoverSidebarProps { const hits = getDataTableRecords(dataView); const dataViewList = [ - { id: '0', attributes: { title: 'b' } } as SavedObject<DataViewAttributes>, - { id: '1', attributes: { title: 'a' } } as SavedObject<DataViewAttributes>, - { id: '2', attributes: { title: 'c' } } as SavedObject<DataViewAttributes>, + { id: '0', title: 'b' } as DataViewListItem, + { id: '1', title: 'a' } as DataViewListItem, + { id: '2', title: 'c' } as DataViewListItem, ]; const fieldCounts: Record<string, number> = {}; diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 05f1e6a960918f..1623a75a621d1e 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -13,8 +13,7 @@ import { getDataTableRecords } from '../../../../__fixtures__/real_hits'; import { act } from 'react-dom/test-utils'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import React from 'react'; -import { DataViewAttributes } from '@kbn/data-views-plugin/public'; -import { SavedObject } from '@kbn/core/types'; +import { DataViewListItem } from '@kbn/data-views-plugin/public'; import { DiscoverSidebarResponsive, DiscoverSidebarResponsiveProps, @@ -78,9 +77,9 @@ function getCompProps(): DiscoverSidebarResponsiveProps { const hits = getDataTableRecords(dataView); const dataViewList = [ - { id: '0', attributes: { title: 'b' } } as SavedObject<DataViewAttributes>, - { id: '1', attributes: { title: 'a' } } as SavedObject<DataViewAttributes>, - { id: '2', attributes: { title: 'c' } } as SavedObject<DataViewAttributes>, + { id: '0', title: 'b' } as DataViewListItem, + { id: '1', title: 'a' } as DataViewListItem, + { id: '2', title: 'c' } as DataViewListItem, ]; for (const hit of hits) { diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx index bc813119342efc..d111c357223466 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx @@ -22,8 +22,7 @@ import { EuiShowFor, EuiTitle, } from '@elastic/eui'; -import type { DataView, DataViewAttributes, DataViewField } from '@kbn/data-views-plugin/public'; -import { SavedObject } from '@kbn/core/types'; +import type { DataView, DataViewField, DataViewListItem } from '@kbn/data-views-plugin/public'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { getDefaultFieldFilter } from './lib/field_filter'; import { DiscoverSidebar } from './discover_sidebar'; @@ -51,7 +50,7 @@ export interface DiscoverSidebarResponsiveProps { /** * List of available data views */ - dataViewList: Array<SavedObject<DataViewAttributes>>; + dataViewList: DataViewListItem[]; /** * Has been toggled closed */ diff --git a/src/plugins/discover/public/application/main/discover_main_app.test.tsx b/src/plugins/discover/public/application/main/discover_main_app.test.tsx index bb7321ede1b8e7..0947891e5095f8 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.test.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.test.tsx @@ -7,12 +7,11 @@ */ import React from 'react'; import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { DataViewListItem } from '@kbn/data-views-plugin/public'; import { dataViewMock } from '../../__mocks__/data_view'; import { DiscoverMainApp } from './discover_main_app'; import { DiscoverTopNav } from './components/top_nav/discover_topnav'; import { savedSearchMock } from '../../__mocks__/saved_search'; -import { SavedObject } from '@kbn/core/types'; -import type { DataViewAttributes } from '@kbn/data-views-plugin/public'; import { setHeaderActionMenuMounter } from '../../kibana_services'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { discoverServiceMock } from '../../__mocks__/services'; @@ -25,7 +24,7 @@ describe('DiscoverMainApp', () => { test('renders', () => { const dataViewList = [dataViewMock].map((ip) => { return { ...ip, ...{ attributes: { title: ip.title } } }; - }) as unknown as Array<SavedObject<DataViewAttributes>>; + }) as unknown as DataViewListItem[]; const props = { dataViewList, savedSearch: savedSearchMock, diff --git a/src/plugins/discover/public/application/main/discover_main_app.tsx b/src/plugins/discover/public/application/main/discover_main_app.tsx index 9b48be3ad1bc81..4d129ae19746f1 100644 --- a/src/plugins/discover/public/application/main/discover_main_app.tsx +++ b/src/plugins/discover/public/application/main/discover_main_app.tsx @@ -7,9 +7,8 @@ */ import React, { useCallback, useEffect, useState } from 'react'; import { useHistory } from 'react-router-dom'; -import type { DataViewAttributes } from '@kbn/data-views-plugin/public'; -import type { SavedObject } from '@kbn/data-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { DataViewListItem } from '@kbn/data-views-plugin/public'; import { DiscoverLayout } from './components/layout'; import { setBreadcrumbsTitle } from '../../utils/breadcrumbs'; import { addHelpMenuToAppChrome } from '../../components/help_menu/help_menu_util'; @@ -25,7 +24,7 @@ export interface DiscoverMainProps { /** * List of available data views */ - dataViewList: Array<SavedObject<DataViewAttributes>>; + dataViewList: DataViewListItem[]; /** * Current instance of SavedSearch */ @@ -35,7 +34,7 @@ export interface DiscoverMainProps { export function DiscoverMainApp(props: DiscoverMainProps) { const { savedSearch, dataViewList } = props; const services = useDiscoverServices(); - const { chrome, docLinks, uiSettings: config, data, spaces, history } = services; + const { chrome, docLinks, data, spaces, history } = services; const usedHistory = useHistory(); const [expandedDoc, setExpandedDoc] = useState<DataTableRecord | undefined>(undefined); const navigateTo = useCallback( @@ -64,6 +63,7 @@ export function DiscoverMainApp(props: DiscoverMainProps) { history: usedHistory, savedSearch, setExpandedDoc, + dataViewList, }); /** @@ -81,7 +81,7 @@ export function DiscoverMainApp(props: DiscoverMainProps) { return () => { data.search.session.clear(); }; - }, [savedSearch, chrome, docLinks, refetch$, stateContainer, data, config]); + }, [savedSearch, chrome, data]); /** * Initializing syncing with state and help menu diff --git a/src/plugins/discover/public/application/main/discover_main_route.tsx b/src/plugins/discover/public/application/main/discover_main_route.tsx index 06727473771b35..4871d498a9bdaa 100644 --- a/src/plugins/discover/public/application/main/discover_main_route.tsx +++ b/src/plugins/discover/public/application/main/discover_main_route.tsx @@ -7,12 +7,9 @@ */ import React, { useEffect, useState, memo, useCallback } from 'react'; import { useParams, useHistory } from 'react-router-dom'; -import { SavedObject } from '@kbn/data-plugin/public'; +import { DataViewListItem } from '@kbn/data-plugin/public'; import { ISearchSource } from '@kbn/data-plugin/public'; -import { - DataViewAttributes, - DataViewSavedObjectConflictError, -} from '@kbn/data-views-plugin/public'; +import { DataViewSavedObjectConflictError } from '@kbn/data-views-plugin/public'; import { redirectWhenMissing } from '@kbn/kibana-utils-plugin/public'; import { useExecutionContext } from '@kbn/kibana-react-plugin/public'; import { @@ -60,7 +57,7 @@ export function DiscoverMainRoute(props: Props) { const [error, setError] = useState<Error>(); const [savedSearch, setSavedSearch] = useState<SavedSearch>(); const dataView = savedSearch?.searchSource?.getField('index'); - const [dataViewList, setDataViewList] = useState<Array<SavedObject<DataViewAttributes>>>([]); + const [dataViewList, setDataViewList] = useState<DataViewListItem[]>([]); const [hasESData, setHasESData] = useState(false); const [hasUserDataView, setHasUserDataView] = useState(false); const [showNoDataPage, setShowNoDataPage] = useState<boolean>(false); @@ -99,7 +96,7 @@ export function DiscoverMainRoute(props: Props) { const { index } = appStateContainer.getState(); const ip = await loadDataView(index || '', data.dataViews, config); - const ipList = ip.list as Array<SavedObject<DataViewAttributes>>; + const ipList = ip.list; const dataViewData = resolveDataView(ip, searchSource, toastNotifications); await data.dataViews.refreshFields(dataViewData); setDataViewList(ipList); diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.test.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.test.ts index c7b6c7a6fe8e7a..40078a4616e8e1 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.test.ts @@ -7,28 +7,14 @@ */ import { renderHook } from '@testing-library/react-hooks'; +import { DataViewListItem, SearchSource } from '@kbn/data-plugin/public'; import { createSearchSessionMock } from '../../../__mocks__/search_session'; import { discoverServiceMock } from '../../../__mocks__/services'; import { savedSearchMock } from '../../../__mocks__/saved_search'; import { useDiscoverState } from './use_discover_state'; import { dataViewMock } from '../../../__mocks__/data_view'; -import { SearchSource } from '@kbn/data-plugin/public'; describe('test useDiscoverState', () => { - const originalSavedObjectsClient = discoverServiceMock.core.savedObjects.client; - - beforeAll(() => { - discoverServiceMock.core.savedObjects.client.resolve = jest.fn().mockReturnValue({ - saved_object: { - attributes: {}, - }, - }); - }); - - afterAll(() => { - discoverServiceMock.core.savedObjects.client = originalSavedObjectsClient; - }); - test('return is valid', async () => { const { history } = createSearchSessionMock(); @@ -38,6 +24,7 @@ describe('test useDiscoverState', () => { history, savedSearch: savedSearchMock, setExpandedDoc: jest.fn(), + dataViewList: [dataViewMock as DataViewListItem], }); }); expect(result.current.state.index).toBe(dataViewMock.id); diff --git a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts index dc06163a5f2c1e..c89d8b206ecf1c 100644 --- a/src/plugins/discover/public/application/main/hooks/use_discover_state.ts +++ b/src/plugins/discover/public/application/main/hooks/use_discover_state.ts @@ -6,23 +6,17 @@ * Side Public License, v 1. */ import { useMemo, useEffect, useState, useCallback } from 'react'; -import usePrevious from 'react-use/lib/usePrevious'; import { isEqual } from 'lodash'; import { History } from 'history'; -import { DataViewType } from '@kbn/data-views-plugin/public'; -import { - isOfAggregateQueryType, - getIndexPatternFromSQLQuery, - AggregateQuery, - Query, -} from '@kbn/es-query'; +import { DataViewListItem, DataViewType } from '@kbn/data-views-plugin/public'; import { SavedSearch, getSavedSearch } from '@kbn/saved-search-plugin/public'; import type { SortOrder } from '@kbn/saved-search-plugin/public'; +import { useTextBasedQueryLanguage } from './use_text_based_query_language'; import { getState } from '../services/discover_state'; import { getStateDefaults } from '../utils/get_state_defaults'; import { DiscoverServices } from '../../../build_services'; import { loadDataView } from '../utils/resolve_data_view'; -import { useSavedSearch as useSavedSearchData, DataDocumentsMsg } from './use_saved_search'; +import { useSavedSearch as useSavedSearchData } from './use_saved_search'; import { MODIFY_COLUMNS_ON_SWITCH, SEARCH_FIELDS_FROM_SOURCE, @@ -30,27 +24,26 @@ import { SORT_DEFAULT_ORDER_SETTING, } from '../../../../common'; import { useSearchSession } from './use_search_session'; -import { useDataState } from './use_data_state'; import { FetchStatus } from '../../types'; import { getDataViewAppState } from '../utils/get_switch_data_view_app_state'; import { DataTableRecord } from '../../../types'; import { restoreStateFromSavedSearch } from '../../../services/saved_searches/restore_from_saved_search'; -const MAX_NUM_OF_COLUMNS = 50; - export function useDiscoverState({ services, history, savedSearch, setExpandedDoc, + dataViewList, }: { services: DiscoverServices; savedSearch: SavedSearch; history: History; setExpandedDoc: (doc?: DataTableRecord) => void; + dataViewList: DataViewListItem[]; }) { - const { uiSettings: config, data, filterManager, dataViews, storage } = services; - const useNewFieldsApi = useMemo(() => !config.get(SEARCH_FIELDS_FROM_SOURCE), [config]); + const { uiSettings, data, filterManager, dataViews, storage } = services; + const useNewFieldsApi = useMemo(() => !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE), [uiSettings]); const { timefilter } = data.query.timefilter; const dataView = savedSearch.searchSource.getField('index')!; @@ -65,25 +58,22 @@ export function useDiscoverState({ getState({ getStateDefaults: () => getStateDefaults({ - config, + config: uiSettings, data, savedSearch, storage, }), - storeInSessionStorage: config.get('state:storeInSessionStorage'), + storeInSessionStorage: uiSettings.get('state:storeInSessionStorage'), history, toasts: services.core.notifications.toasts, - uiSettings: config, + uiSettings, }), - [config, data, history, savedSearch, services.core.notifications.toasts, storage] + [uiSettings, data, history, savedSearch, services.core.notifications.toasts, storage] ); const { appStateContainer } = stateContainer; const [state, setState] = useState(appStateContainer.getState()); - const [documentStateCols, setDocumentStateCols] = useState<string[]>([]); - const [sqlQuery] = useState<AggregateQuery | Query | undefined>(state.query); - const prevQuery = usePrevious(state.query); /** * Search session logic @@ -94,12 +84,12 @@ export function useDiscoverState({ // A saved search is created on every page load, so we check the ID to see if we're loading a // previously saved search or if it is just transient const shouldSearchOnPageLoad = - config.get<boolean>(SEARCH_ON_PAGE_LOAD_SETTING) || + uiSettings.get<boolean>(SEARCH_ON_PAGE_LOAD_SETTING) || savedSearch.id !== undefined || timefilter.getRefreshInterval().pause === false || searchSessionManager.hasSearchSessionIdInURL(); return shouldSearchOnPageLoad ? FetchStatus.LOADING : FetchStatus.UNINITIALIZED; - }, [config, savedSearch.id, searchSessionManager, timefilter]); + }, [uiSettings, savedSearch.id, searchSessionManager, timefilter]); /** * Data fetching logic @@ -113,8 +103,16 @@ export function useDiscoverState({ stateContainer, useNewFieldsApi, }); - - const documentState: DataDocumentsMsg = useDataState(data$.documents$); + /** + * State changes (data view, columns), when a text base query result is returned + */ + useTextBasedQueryLanguage({ + documents$: data$.documents$, + dataViews, + stateContainer, + dataViewList, + savedSearch, + }); /** * Reset to display loading spinner when savedSearch is changing @@ -151,7 +149,11 @@ export function useDiscoverState({ * That's because appState is updated before savedSearchData$ * The following line of code catches this, but should be improved */ - const nextDataView = await loadDataView(nextState.index, dataViews, config); + const nextDataView = await loadDataView( + nextState.index, + services.dataViews, + services.uiSettings + ); savedSearch.searchSource.setField('index', nextDataView.loaded); reset(); @@ -163,17 +165,7 @@ export function useDiscoverState({ setState(nextState); }); return () => unsubscribe(); - }, [ - config, - dataViews, - appStateContainer, - setState, - state, - refetch$, - data$, - reset, - savedSearch.searchSource, - ]); + }, [services, appStateContainer, state, refetch$, data$, reset, savedSearch.searchSource]); /** * function to revert any changes to a given saved search @@ -190,7 +182,7 @@ export function useDiscoverState({ const newDataView = newSavedSearch.searchSource.getField('index') || dataView; newSavedSearch.searchSource.setField('index', newDataView); const newAppState = getStateDefaults({ - config, + config: uiSettings, data, savedSearch: newSavedSearch, storage, @@ -204,7 +196,7 @@ export function useDiscoverState({ await stateContainer.replaceUrlAppState(newAppState); setState(newAppState); }, - [services, dataView, config, data, storage, stateContainer] + [services, dataView, uiSettings, data, storage, stateContainer] ); /** @@ -219,8 +211,8 @@ export function useDiscoverState({ nextDataView, state.columns || [], (state.sort || []) as SortOrder[], - config.get(MODIFY_COLUMNS_ON_SWITCH), - config.get(SORT_DEFAULT_ORDER_SETTING), + uiSettings.get(MODIFY_COLUMNS_ON_SWITCH), + uiSettings.get(SORT_DEFAULT_ORDER_SETTING), state.query ); stateContainer.setAppState(nextAppState); @@ -228,7 +220,7 @@ export function useDiscoverState({ setExpandedDoc(undefined); }, [ - config, + uiSettings, dataView, dataViews, setExpandedDoc, @@ -254,12 +246,6 @@ export function useDiscoverState({ /** * Trigger data fetching on dataView or savedSearch changes */ - useEffect(() => { - if (!isEqual(state.query, prevQuery)) { - setDocumentStateCols([]); - } - }, [state.query, prevQuery]); - useEffect(() => { if (dataView) { refetch$.next(undefined); @@ -276,41 +262,6 @@ export function useDiscoverState({ } }, [dataView, stateContainer]); - const getResultColumns = useCallback(() => { - if (documentState.result?.length && documentState.fetchStatus === FetchStatus.COMPLETE) { - const firstRow = documentState.result[0]; - const columns = Object.keys(firstRow.raw).slice(0, MAX_NUM_OF_COLUMNS); - if (!isEqual(columns, documentStateCols) && !isEqual(state.query, sqlQuery)) { - return columns; - } - return []; - } - return []; - }, [documentState, documentStateCols, sqlQuery, state.query]); - - useEffect(() => { - async function fetchDataview() { - if (state.query && isOfAggregateQueryType(state.query) && 'sql' in state.query) { - const indexPatternFromQuery = getIndexPatternFromSQLQuery(state.query.sql); - const idsTitles = await dataViews.getIdsWithTitle(); - const dataViewObj = idsTitles.find(({ title }) => title === indexPatternFromQuery); - if (dataViewObj) { - const columns = getResultColumns(); - if (columns.length) { - setDocumentStateCols(columns); - } - const nextState = { - index: dataViewObj.id, - ...(columns.length && { columns }), - }; - stateContainer.replaceUrlAppState(nextState); - } - } - } - fetchDataview(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [config, documentState, dataViews]); - return { data$, dataView, diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts index 1f3dfdbf39771f..41b8348a3a26df 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search.test.ts @@ -15,6 +15,8 @@ import { getState, AppState } from '../services/discover_state'; import { uiSettingsMock } from '../../../__mocks__/ui_settings'; import { useDiscoverState } from './use_discover_state'; import { FetchStatus } from '../../types'; +import { dataViewMock } from '../../../__mocks__/data_view'; +import { DataViewListItem } from '@kbn/data-views-plugin/common'; describe('test useSavedSearch', () => { test('useSavedSearch return is valid', async () => { @@ -61,6 +63,7 @@ describe('test useSavedSearch', () => { history, savedSearch: savedSearchMock, setExpandedDoc: jest.fn(), + dataViewList: [dataViewMock as DataViewListItem], }); }); @@ -104,6 +107,7 @@ describe('test useSavedSearch', () => { history, savedSearch: savedSearchMock, setExpandedDoc: jest.fn(), + dataViewList: [dataViewMock as DataViewListItem], }); }); diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts index 3b9948f88d17e3..4762748e2618b7 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search.ts @@ -11,6 +11,7 @@ import type { AutoRefreshDoneFn } from '@kbn/data-plugin/public'; import { ISearchSource } from '@kbn/data-plugin/public'; import { RequestAdapter } from '@kbn/inspector-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { AggregateQuery, Query } from '@kbn/es-query'; import { getRawRecordType } from '../utils/get_raw_record_type'; import { DiscoverServices } from '../../../build_services'; import { DiscoverSearchSessionManager } from '../services/discover_search_session'; @@ -71,6 +72,7 @@ export interface DataMsg { fetchStatus: FetchStatus; error?: Error; recordRawType?: RecordRawType; + query?: AggregateQuery | Query | undefined; } export interface DataMainMsg extends DataMsg { diff --git a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts index a17f33b5270c1c..0d6caf180a3f61 100644 --- a/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts +++ b/src/plugins/discover/public/application/main/hooks/use_saved_search_messages.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { AggregateQuery, Query } from '@kbn/es-query'; import { FetchStatus } from '../../types'; import { DataCharts$, @@ -61,12 +62,14 @@ export function sendPartialMsg(main$: DataMain$) { */ export function sendLoadingMsg( data$: DataMain$ | DataDocuments$ | DataTotalHits$ | DataCharts$, - recordRawType: RecordRawType + recordRawType: RecordRawType, + query?: AggregateQuery | Query ) { if (data$.getValue().fetchStatus !== FetchStatus.LOADING) { data$.next({ fetchStatus: FetchStatus.LOADING, recordRawType, + query, }); } } diff --git a/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts new file mode 100644 index 00000000000000..4efbfe827c4bda --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/use_test_based_query_language.test.ts @@ -0,0 +1,249 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import { waitFor } from '@testing-library/react'; +import { discoverServiceMock } from '../../../__mocks__/services'; +import { useTextBasedQueryLanguage } from './use_text_based_query_language'; +import { AppState, GetStateReturn } from '../services/discover_state'; +import { BehaviorSubject } from 'rxjs'; +import { FetchStatus } from '../../types'; +import { DataDocuments$, RecordRawType } from './use_saved_search'; +import { DataTableRecord } from '../../../types'; +import { AggregateQuery, Query } from '@kbn/es-query'; +import { dataViewMock } from '../../../__mocks__/data_view'; +import { DataViewListItem } from '@kbn/data-views-plugin/common'; +import { savedSearchMock } from '../../../__mocks__/saved_search'; + +function getHookProps( + replaceUrlAppState: (newState: Partial<AppState>) => Promise<void>, + query: AggregateQuery | Query | undefined +) { + const stateContainer = { + replaceUrlAppState, + appStateContainer: { + getState: () => { + return []; + }, + }, + } as unknown as GetStateReturn; + + const msgLoading = { + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.LOADING, + query, + }; + + const documents$ = new BehaviorSubject(msgLoading) as DataDocuments$; + + return { + documents$, + dataViews: discoverServiceMock.dataViews, + stateContainer, + dataViewList: [dataViewMock as DataViewListItem], + savedSearch: savedSearchMock, + }; +} +const query = { sql: 'SELECT * from the-data-view-title' }; +const msgComplete = { + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1, field2: 2 }, + flattened: { field1: 1, field2: 2 }, + } as unknown as DataTableRecord, + ], + query, +}; + +describe('useTextBasedQueryLanguage', () => { + test('a text based query should change state when loading and finished', async () => { + const replaceUrlAppState = jest.fn(); + const props = getHookProps(replaceUrlAppState, query); + const { documents$ } = props; + + renderHook(() => useTextBasedQueryLanguage(props)); + + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + expect(replaceUrlAppState).toHaveBeenCalledWith({ index: 'the-data-view-id' }); + + replaceUrlAppState.mockReset(); + + documents$.next(msgComplete); + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + + await waitFor(() => { + expect(replaceUrlAppState).toHaveBeenCalledWith({ + index: 'the-data-view-id', + columns: ['field1', 'field2'], + }); + }); + }); + test('changing a text based query with different result columns should change state when loading and finished', async () => { + const replaceUrlAppState = jest.fn(); + const props = getHookProps(replaceUrlAppState, query); + const { documents$ } = props; + + renderHook(() => useTextBasedQueryLanguage(props)); + + documents$.next(msgComplete); + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(2)); + replaceUrlAppState.mockReset(); + + documents$.next({ + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + query: { sql: 'SELECT field1 from the-data-view-title' }, + }); + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + + await waitFor(() => { + expect(replaceUrlAppState).toHaveBeenCalledWith({ + index: 'the-data-view-id', + columns: ['field1'], + }); + }); + }); + test('only changing a text based query with same result columns should not change columns', async () => { + const replaceUrlAppState = jest.fn(); + const props = getHookProps(replaceUrlAppState, query); + const { documents$ } = props; + + renderHook(() => useTextBasedQueryLanguage(props)); + + documents$.next(msgComplete); + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(2)); + replaceUrlAppState.mockReset(); + + documents$.next({ + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + query: { sql: 'SELECT field1 from the-data-view-title' }, + }); + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + replaceUrlAppState.mockReset(); + + documents$.next({ + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + query: { sql: 'SELECT field1 from the-data-view-title WHERE field1=1' }, + }); + + await waitFor(() => { + expect(replaceUrlAppState).toHaveBeenCalledWith({ + index: 'the-data-view-id', + }); + }); + }); + test('if its not a text based query coming along, it should be ignored', async () => { + const replaceUrlAppState = jest.fn(); + const props = getHookProps(replaceUrlAppState, query); + const { documents$ } = props; + + renderHook(() => useTextBasedQueryLanguage(props)); + + documents$.next(msgComplete); + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(2)); + replaceUrlAppState.mockReset(); + + documents$.next({ + recordRawType: RecordRawType.DOCUMENT, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + }); + + documents$.next({ + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + query: { sql: 'SELECT field1 from the-data-view-title WHERE field1=1' }, + }); + + await waitFor(() => { + expect(replaceUrlAppState).toHaveBeenCalledWith({ + index: 'the-data-view-id', + columns: ['field1'], + }); + }); + }); + + test('it should not overwrite existing state columns on initial fetch', async () => { + const replaceUrlAppState = jest.fn(); + const props = getHookProps(replaceUrlAppState, query); + props.stateContainer.appStateContainer.getState = jest.fn(() => { + return { columns: ['field1'], index: 'the-data-view-id' }; + }); + const { documents$ } = props; + + renderHook(() => useTextBasedQueryLanguage(props)); + documents$.next({ + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1, field2: 2 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + query: { sql: 'SELECT field1 from the-data-view-title WHERE field1=1' }, + }); + + documents$.next({ + recordRawType: RecordRawType.PLAIN, + fetchStatus: FetchStatus.COMPLETE, + result: [ + { + id: '1', + raw: { field1: 1 }, + flattened: { field1: 1 }, + } as unknown as DataTableRecord, + ], + query: { sql: 'SELECT field1 from the-data-view-title' }, + }); + await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + expect(replaceUrlAppState).toHaveBeenCalledWith({ + columns: ['field1'], + }); + }); +}); diff --git a/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts b/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts new file mode 100644 index 00000000000000..71732bfaf6f27f --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/use_text_based_query_language.ts @@ -0,0 +1,113 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { isEqual } from 'lodash'; +import { + isOfAggregateQueryType, + getIndexPatternFromSQLQuery, + AggregateQuery, + Query, +} from '@kbn/es-query'; +import { useCallback, useEffect, useRef } from 'react'; +import { DataViewListItem, DataViewsContract } from '@kbn/data-views-plugin/public'; +import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import type { GetStateReturn } from '../services/discover_state'; +import type { DataDocuments$ } from './use_saved_search'; +import { FetchStatus } from '../../types'; + +const MAX_NUM_OF_COLUMNS = 50; + +/** + * Hook to take care of text based query language state transformations when a new result is returned + * If necessary this is setting displayed columns and selected data view + */ +export function useTextBasedQueryLanguage({ + documents$, + dataViews, + stateContainer, + dataViewList, + savedSearch, +}: { + documents$: DataDocuments$; + stateContainer: GetStateReturn; + dataViews: DataViewsContract; + dataViewList: DataViewListItem[]; + savedSearch: SavedSearch; +}) { + const prev = useRef<{ query: AggregateQuery | Query | undefined; columns: string[] }>({ + columns: [], + query: undefined, + }); + + const cleanup = useCallback(() => { + if (prev.current.query) { + // cleanup when it's not a text based query lang + prev.current = { + columns: [], + query: undefined, + }; + } + }, []); + + useEffect(() => { + const subscription = documents$.subscribe(async (next) => { + const { query } = next; + const { columns: stateColumns, index } = stateContainer.appStateContainer.getState(); + let nextColumns: string[] = []; + const isTextBasedQueryLang = + next.recordRawType === 'plain' && query && isOfAggregateQueryType(query) && 'sql' in query; + const hasResults = next.result?.length && next.fetchStatus === FetchStatus.COMPLETE; + const initialFetch = !prev.current.columns.length; + + if (isTextBasedQueryLang) { + if (hasResults) { + // check if state needs to contain column transformation due to a different columns in the resultset + const firstRow = next.result![0]; + const firstRowColumns = Object.keys(firstRow.raw).slice(0, MAX_NUM_OF_COLUMNS); + if ( + !isEqual(firstRowColumns, prev.current.columns) && + !isEqual(query, prev.current.query) + ) { + nextColumns = firstRowColumns; + prev.current = { columns: nextColumns, query }; + } + if (firstRowColumns && initialFetch) { + prev.current = { columns: firstRowColumns, query }; + } + } + const indexPatternFromQuery = getIndexPatternFromSQLQuery(query.sql); + const dataViewObj = dataViewList.find(({ title }) => title === indexPatternFromQuery); + + if (dataViewObj) { + // don't set the columns on initial fetch, to prevent overwriting existing state + const addColumnsToState = Boolean( + nextColumns.length && (!initialFetch || !stateColumns?.length) + ); + // no need to reset index to state if it hasn't changed + const addDataViewToState = Boolean(dataViewObj.id !== index); + if (!addColumnsToState && !addDataViewToState) { + return; + } + + const nextState = { + ...(addDataViewToState && { index: dataViewObj.id }), + ...(addColumnsToState && { columns: nextColumns }), + }; + stateContainer.replaceUrlAppState(nextState); + } + } else { + // cleanup for a "regular" query + cleanup(); + } + }); + return () => { + // cleanup for e.g. when savedSearch is switched + cleanup(); + subscription.unsubscribe(); + }; + }, [documents$, dataViews, stateContainer, dataViewList, savedSearch, cleanup]); +} diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts index 47566ed1095d3f..288595fa5f7a5d 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.test.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.test.ts @@ -242,10 +242,11 @@ describe('test fetchAll', () => { ]; const documents = hits.map((hit) => buildDataTableRecord(hit, dataViewMock)); mockFetchSQL.mockResolvedValue(documents); + const query = { sql: 'SELECT * from foo' }; deps = { appStateContainer: { getState: () => { - return { interval: 'auto', query: { sql: 'SELECT * from foo' } }; + return { interval: 'auto', query }; }, } as unknown as ReduxLikeStateContainer<AppState>, abortController: new AbortController(), @@ -260,11 +261,12 @@ describe('test fetchAll', () => { await fetchAll(subjects, searchSource, false, deps); expect(await collect()).toEqual([ { fetchStatus: FetchStatus.UNINITIALIZED }, - { fetchStatus: FetchStatus.LOADING, recordRawType: 'plain' }, + { fetchStatus: FetchStatus.LOADING, recordRawType: 'plain', query }, { fetchStatus: FetchStatus.COMPLETE, recordRawType: 'plain', result: documents, + query, }, ]); }); diff --git a/src/plugins/discover/public/application/main/utils/fetch_all.ts b/src/plugins/discover/public/application/main/utils/fetch_all.ts index 42b415630e92c5..853ae6cebfb76a 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_all.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_all.ts @@ -65,7 +65,7 @@ export function fetchAll( const { initialFetchStatus, appStateContainer, services, useNewFieldsApi, data } = fetchDeps; /** - * Method to create a an error handler that will forward the received error + * Method to create an error handler that will forward the received error * to the specified subjects. It will ignore AbortErrors and will use the data * plugin to show a toast for the error (e.g. allowing better insights into shard failures). */ @@ -103,7 +103,7 @@ export function fetchAll( // Mark all subjects as loading sendLoadingMsg(dataSubjects.main$, recordRawType); - sendLoadingMsg(dataSubjects.documents$, recordRawType); + sendLoadingMsg(dataSubjects.documents$, recordRawType, query); sendLoadingMsg(dataSubjects.totalHits$, recordRawType); sendLoadingMsg(dataSubjects.charts$, recordRawType); @@ -152,6 +152,7 @@ export function fetchAll( fetchStatus: FetchStatus.COMPLETE, result: docs, recordRawType, + query, }); checkHitCount(docs.length); diff --git a/src/plugins/discover/public/application/main/utils/resolve_data_view.test.ts b/src/plugins/discover/public/application/main/utils/resolve_data_view.test.ts index 9db54b596f8354..2b5f0a4a9563a4 100644 --- a/src/plugins/discover/public/application/main/utils/resolve_data_view.test.ts +++ b/src/plugins/discover/public/application/main/utils/resolve_data_view.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { loadDataView, getFallbackDataViewId, DataViewSavedObject } from './resolve_data_view'; +import { loadDataView, getFallbackDataViewId } from './resolve_data_view'; import { dataViewsMock } from '../../../__mocks__/data_views'; import { dataViewMock } from '../../../__mocks__/data_view'; import { configMock } from '../../../__mocks__/config'; @@ -31,8 +31,8 @@ describe('Resolve data view tests', () => { expect(result).toBe(''); }); test('getFallbackDataViewId with an dataViews array', async () => { - const list = await dataViewsMock.getCache(); - const result = await getFallbackDataViewId(list as unknown as DataViewSavedObject[], ''); + const list = await dataViewsMock.getIdsWithTitle(); + const result = await getFallbackDataViewId(list, ''); expect(result).toBe('the-data-view-id'); }); }); diff --git a/src/plugins/discover/public/application/main/utils/resolve_data_view.ts b/src/plugins/discover/public/application/main/utils/resolve_data_view.ts index 3745d6130c01f3..b56abfcf316ae8 100644 --- a/src/plugins/discover/public/application/main/utils/resolve_data_view.ts +++ b/src/plugins/discover/public/application/main/utils/resolve_data_view.ts @@ -7,16 +7,14 @@ */ import { i18n } from '@kbn/i18n'; -import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; +import type { DataView, DataViewListItem, DataViewsContract } from '@kbn/data-views-plugin/public'; import type { ISearchSource } from '@kbn/data-plugin/public'; -import type { IUiSettingsClient, SavedObject, ToastsStart } from '@kbn/core/public'; -export type DataViewSavedObject = SavedObject & { title: string }; - +import type { IUiSettingsClient, ToastsStart } from '@kbn/core/public'; interface DataViewData { /** * List of existing data views */ - list: DataViewSavedObject[]; + list: DataViewListItem[]; /** * Loaded data view (might be default data view if requested was not found) */ @@ -32,9 +30,9 @@ interface DataViewData { } export function findDataViewById( - dataViews: DataViewSavedObject[], + dataViews: DataViewListItem[], id: string -): DataViewSavedObject | undefined { +): DataViewListItem | undefined { if (!Array.isArray(dataViews) || !id) { return; } @@ -46,7 +44,7 @@ export function findDataViewById( * the first available data view id if not */ export function getFallbackDataViewId( - dataViews: DataViewSavedObject[], + dataViews: DataViewListItem[], defaultIndex: string = '' ): string { if (defaultIndex && findDataViewById(dataViews, defaultIndex)) { @@ -62,7 +60,7 @@ export function getFallbackDataViewId( */ export function getDataViewId( id: string = '', - dataViews: DataViewSavedObject[] = [], + dataViews: DataViewListItem[] = [], defaultIndex: string = '' ): string { if (!id || !findDataViewById(dataViews, id)) { @@ -79,7 +77,7 @@ export async function loadDataView( dataViews: DataViewsContract, config: IUiSettingsClient ): Promise<DataViewData> { - const dataViewList = (await dataViews.getCache()) as unknown as DataViewSavedObject[]; + const dataViewList = await dataViews.getIdsWithTitle(); const actualId = getDataViewId(id, dataViewList, config.get('defaultIndex')); return { From 11b6ca8160708b3943f9a3df6acfa2de6e2d5fb6 Mon Sep 17 00:00:00 2001 From: Shahzad <shahzad.muhammad@elastic.co> Date: Mon, 12 Sep 2022 18:28:28 +0200 Subject: [PATCH 078/144] [Fleet] Enhance fleet package policies bulkCreate API (#140513) --- .../fleet/server/services/agent_policy.ts | 6 ++- .../fleet/server/services/package_policy.ts | 45 ++++++++++++++----- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index ffd71c2d6af069..606cf82f10b31f 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -469,8 +469,10 @@ class AgentPolicyService { await packagePolicyService.bulkCreate( soClient, esClient, - newPackagePolicies, - newAgentPolicy.id, + newPackagePolicies.map((newPackagePolicy) => ({ + ...newPackagePolicy, + policy_id: newAgentPolicy.id, + })), { ...options, bumpRevision: false, diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 134abb86b68931..2d02e0e710f772 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -228,26 +228,37 @@ class PackagePolicyService implements PackagePolicyServiceInterface { public async bulkCreate( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - packagePolicies: NewPackagePolicy[], - agentPolicyId: string, - options?: { user?: AuthenticatedUser; bumpRevision?: boolean; force: true } + packagePolicies: NewPackagePolicyWithId[], + options?: { + user?: AuthenticatedUser; + bumpRevision?: boolean; + force?: true; + } ): Promise<PackagePolicy[]> { - await validateIsNotHostedPolicy(soClient, agentPolicyId); + const agentPolicyIds = new Set(packagePolicies.map((pkgPol) => pkgPol.policy_id)); + + for (const agentPolicyId of agentPolicyIds) { + await validateIsNotHostedPolicy(soClient, agentPolicyId, options?.force); + } + const isoDate = new Date().toISOString(); // eslint-disable-next-line @typescript-eslint/naming-convention const { saved_objects } = await soClient.bulkCreate<PackagePolicySOAttributes>( packagePolicies.map((packagePolicy) => { - const packagePolicyId = uuid.v4(); + const packagePolicyId = packagePolicy.id ?? uuid.v4(); + const agentPolicyId = packagePolicy.policy_id; const inputs = packagePolicy.inputs.map((input) => assignStreamIdToInput(packagePolicyId, input) ); + const { id, ...pkgPolicyWithoutId } = packagePolicy; + return { type: SAVED_OBJECT_TYPE, id: packagePolicyId, attributes: { - ...packagePolicy, + ...pkgPolicyWithoutId, inputs, policy_id: agentPolicyId, revision: 1, @@ -266,9 +277,11 @@ class PackagePolicyService implements PackagePolicyServiceInterface { // Assign it to the given agent policy if (options?.bumpRevision ?? true) { - await agentPolicyService.bumpRevision(soClient, esClient, agentPolicyId, { - user: options?.user, - }); + for (const agentPolicyIdT of agentPolicyIds) { + await agentPolicyService.bumpRevision(soClient, esClient, agentPolicyIdT, { + user: options?.user, + }); + } } return newSos.map((newSo) => ({ @@ -1339,6 +1352,11 @@ function _enforceFrozenVars( return resultVars; } +export interface NewPackagePolicyWithId extends NewPackagePolicy { + id?: string; + policy_id: string; +} + export interface PackagePolicyServiceInterface { create( soClient: SavedObjectsClientContract, @@ -1360,9 +1378,12 @@ export interface PackagePolicyServiceInterface { bulkCreate( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - packagePolicies: NewPackagePolicy[], - agentPolicyId: string, - options?: { user?: AuthenticatedUser; bumpRevision?: boolean } + packagePolicies: NewPackagePolicyWithId[], + options?: { + user?: AuthenticatedUser; + bumpRevision?: boolean; + force?: true; + } ): Promise<PackagePolicy[]>; get(soClient: SavedObjectsClientContract, id: string): Promise<PackagePolicy | null>; From 1a30682fcecd62750c8b8819eb04a36afa44811c Mon Sep 17 00:00:00 2001 From: Andrew Tate <andrew.tate@elastic.co> Date: Mon, 12 Sep 2022 12:17:04 -0500 Subject: [PATCH 079/144] [Lens] collapse by for partition charts (#140336) --- x-pack/plugins/lens/common/types.ts | 1 + .../config_panel/layer_panel.test.tsx | 46 +++++ .../editor_frame/config_panel/layer_panel.tsx | 44 +++-- x-pack/plugins/lens/public/types.ts | 1 + .../visualizations/partition/to_expression.ts | 22 ++- .../visualizations/partition/toolbar.tsx | 50 +++++- .../partition/visualization.test.ts | 167 +++++++++++++++++- .../partition/visualization.tsx | 105 ++++++++--- 8 files changed, 386 insertions(+), 50 deletions(-) diff --git a/x-pack/plugins/lens/common/types.ts b/x-pack/plugins/lens/common/types.ts index f4ad9e4fb4a760..bb176babf9d2f9 100644 --- a/x-pack/plugins/lens/common/types.ts +++ b/x-pack/plugins/lens/common/types.ts @@ -66,6 +66,7 @@ export interface SharedPieLayerState { primaryGroups: string[]; secondaryGroups?: string[]; metric?: string; + collapseFns?: Record<string, string>; numberDisplay: NumberDisplayType; categoryDisplay: CategoryDisplayType; legendDisplay: LegendDisplayType; diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx index 0440700c7ed8b6..cb45519250a81d 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx @@ -249,6 +249,52 @@ describe('LayerPanel', () => { expect(group).toHaveLength(1); }); + it('should tell the user to remove the correct number of dimensions', async () => { + mockVisualization.getConfiguration.mockReturnValue({ + groups: [ + { + groupLabel: 'A', + groupId: 'a', + accessors: [{ columnId: 'x' }], + filterOperations: () => true, + supportsMoreColumns: false, + dataTestSubj: 'lnsGroup', + dimensionsTooMany: 1, + }, + { + groupLabel: 'A', + groupId: 'a', + accessors: [{ columnId: 'x' }], + filterOperations: () => true, + supportsMoreColumns: false, + dataTestSubj: 'lnsGroup', + dimensionsTooMany: -1, + }, + { + groupLabel: 'B', + groupId: 'b', + accessors: [], + filterOperations: () => true, + supportsMoreColumns: true, + dataTestSubj: 'lnsGroup', + dimensionsTooMany: 3, + }, + ], + }); + + const { instance } = await mountWithProvider(<LayerPanel {...getDefaultProps()} />); + + const groups = instance.find(EuiFormRow); + + expect(groups.findWhere((e) => e.prop('error') === 'Please remove a dimension')).toHaveLength( + 1 + ); + expect( + groups.findWhere((e) => e.prop('error') === 'Please remove 3 dimensions') + ).toHaveLength(1); + expect(groups.findWhere((e) => e.prop('error') === '')).toHaveLength(1); + }); + it('should render the required warning when only one group is configured (with requiredMinDimensionCount)', async () => { mockVisualization.getConfiguration.mockReturnValue({ groups: [ diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 65008196c4b8fe..d1ab12342dd83d 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -370,26 +370,36 @@ export function LayerPanel( </header> {groups.map((group, groupIndex) => { - let isMissing = false; + let errorText: string = ''; if (!isEmptyLayer) { if (group.requiredMinDimensionCount) { - isMissing = group.accessors.length < group.requiredMinDimensionCount; - } else if (group.required) { - isMissing = group.accessors.length === 0; - } - } - - const isMissingError = group.requiredMinDimensionCount - ? i18n.translate('xpack.lens.editorFrame.requiresTwoOrMoreFieldsWarningLabel', { - defaultMessage: 'Requires {requiredMinDimensionCount} fields', - values: { - requiredMinDimensionCount: group.requiredMinDimensionCount, - }, - }) - : i18n.translate('xpack.lens.editorFrame.requiresFieldWarningLabel', { + errorText = i18n.translate( + 'xpack.lens.editorFrame.requiresTwoOrMoreFieldsWarningLabel', + { + defaultMessage: 'Requires {requiredMinDimensionCount} fields', + values: { + requiredMinDimensionCount: group.requiredMinDimensionCount, + }, + } + ); + } else if (group.required && group.accessors.length === 0) { + errorText = i18n.translate('xpack.lens.editorFrame.requiresFieldWarningLabel', { defaultMessage: 'Requires field', }); + } else if (group.dimensionsTooMany && group.dimensionsTooMany > 0) { + errorText = i18n.translate( + 'xpack.lens.editorFrame.tooManyDimensionsSingularWarningLabel', + { + defaultMessage: + 'Please remove {dimensionsTooMany, plural, one {a dimension} other {{dimensionsTooMany} dimensions}}', + values: { + dimensionsTooMany: group.dimensionsTooMany, + }, + } + ); + } + } const isOptional = !group.required && !group.suggestedValue; return ( <EuiFormRow @@ -425,8 +435,8 @@ export function LayerPanel( } labelType="legend" key={group.groupId} - isInvalid={isMissing} - error={isMissing ? isMissingError : []} + isInvalid={Boolean(errorText)} + error={errorText} > <> {group.accessors.length ? ( diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 17950f8c5e50e6..a292d50cab8953 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -712,6 +712,7 @@ export type VisualizationDimensionGroupConfig = SharedDimensionProps & { groupId: string; accessors: AccessorConfig[]; supportsMoreColumns: boolean; + dimensionsTooMany?: number; /** If required, a warning will appear if accessors are empty */ required?: boolean; requiredMinDimensionCount?: number; diff --git a/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts b/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts index 5aeb9807b1eb34..3f66965dc98b6c 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { Ast } from '@kbn/interpreter'; +import type { Ast, AstFunction } from '@kbn/interpreter'; import { Position } from '@elastic/charts'; import type { PaletteOutput, PaletteRegistry } from '@kbn/coloring'; @@ -23,6 +23,7 @@ import { LegendDisplay, } from '../../../common'; import { getDefaultVisualValuesForLayer } from '../../shared_components/datasource_default_values'; +import { isCollapsed } from './visualization'; interface Attributes { isPreview: boolean; @@ -142,7 +143,10 @@ const generateCommonArguments: GenerateExpressionAstArguments = ( ) => { return { labels: generateCommonLabelsAstArgs(state, attributes, layer), - buckets: operations.map((o) => o.columnId).map(prepareDimension), + buckets: operations + .filter(({ columnId }) => !isCollapsed(columnId, layer)) + .map(({ columnId }) => columnId) + .map(prepareDimension), metric: layer.metric ? [prepareDimension(layer.metric)] : [], legendDisplay: [attributes.isPreview ? LegendDisplay.HIDE : layer.legendDisplay], legendPosition: [layer.legendPosition || Position.Right], @@ -218,6 +222,7 @@ const generateMosaicVisAst: GenerateExpressionAstFunction = (...rest) => ({ ...generateCommonArguments(...rest), // flip order of bucket dimensions so the rows are fetched before the columns to keep them stable buckets: rest[2] + .filter(({ columnId }) => !isCollapsed(columnId, rest[3])) .reverse() .map((o) => o.columnId) .map(prepareDimension), @@ -298,6 +303,19 @@ function expressionHelper( type: 'expression', chain: [ ...(datasourceAst ? datasourceAst.chain : []), + ...groups + .filter((columnId) => layer.collapseFns?.[columnId]) + .map((columnId) => { + return { + type: 'function', + function: 'lens_collapse', + arguments: { + by: groups.filter((chk) => chk !== columnId), + metric: [layer.metric], + fn: [layer.collapseFns![columnId]!], + }, + } as AstFunction; + }), ...(visualizationAst ? visualizationAst.chain : []), ], }; diff --git a/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx b/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx index c6b783298e3cd1..4dcb01c3e93f92 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/toolbar.tsx @@ -31,6 +31,8 @@ import { } from '../../shared_components'; import { getDefaultVisualValuesForLayer } from '../../shared_components/datasource_default_values'; import { shouldShowValuesInLegend } from './render_helpers'; +import { CollapseSetting } from '../../shared_components/collapse_setting'; +import { isCollapsed } from './visualization'; const legendOptions: Array<{ value: SharedPieLayerState['legendDisplay']; @@ -306,14 +308,46 @@ export function DimensionEditor( paletteService: PaletteRegistry; } ) { - if (props.accessor !== Object.values(props.state.layers)[0].primaryGroups[0]) return null; + const currentLayer = props.state.layers.find((layer) => layer.layerId === props.layerId); + + if (!currentLayer) { + return null; + } + + const firstNonCollapsedColumnId = currentLayer.primaryGroups.find( + (columnId) => !isCollapsed(columnId, currentLayer) + ); + return ( - <PalettePicker - palettes={props.paletteService} - activePalette={props.state.palette} - setPalette={(newPalette) => { - props.setState({ ...props.state, palette: newPalette }); - }} - /> + <> + {props.accessor === firstNonCollapsedColumnId && ( + <PalettePicker + palettes={props.paletteService} + activePalette={props.state.palette} + setPalette={(newPalette) => { + props.setState({ ...props.state, palette: newPalette }); + }} + /> + )} + <CollapseSetting + value={currentLayer?.collapseFns?.[props.accessor] || ''} + onChange={(collapseFn: string) => { + props.setState({ + ...props.state, + layers: props.state.layers.map((layer) => + layer.layerId !== props.layerId + ? layer + : { + ...layer, + collapseFns: { + ...layer.collapseFns, + [props.accessor]: collapseFn, + }, + } + ), + }); + }} + /> + </> ); } diff --git a/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts index b89c352cb506e4..82073f1d5d60f1 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts @@ -18,6 +18,8 @@ import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { createMockDatasource, createMockFramePublicAPI } from '../../mocks'; import { FramePublicAPI } from '../../types'; import { themeServiceMock } from '@kbn/core/public/mocks'; +import { cloneDeep } from 'lodash'; +import { PartitionChartsMeta } from './partition_charts_meta'; jest.mock('../../id_generator'); @@ -59,10 +61,26 @@ function mockFrame(): FramePublicAPI { // Just a basic bootstrap here to kickstart the tests describe('pie_visualization', () => { describe('#getErrorMessages', () => { - it('returns undefined if no error is raised', () => { - const error = pieVisualization.getErrorMessages(getExampleState()); + describe('too many dimensions', () => { + const state = { ...getExampleState(), shape: PieChartTypes.MOSAIC }; + const colIds = new Array(PartitionChartsMeta.mosaic.maxBuckets + 1) + .fill(undefined) + .map((_, i) => String(i + 1)); - expect(error).not.toBeDefined(); + state.layers[0].primaryGroups = colIds.slice(0, 2); + state.layers[0].secondaryGroups = colIds.slice(2); + + it('returns error', () => { + expect(pieVisualization.getErrorMessages(state)).toHaveLength(1); + }); + + it("doesn't count collapsed dimensions", () => { + state.layers[0].collapseFns = { + [colIds[0]]: 'some-fn', + }; + + expect(pieVisualization.getErrorMessages(state)).toHaveLength(0); + }); }); }); @@ -111,4 +129,147 @@ describe('pie_visualization', () => { ); }); }); + + describe('#removeDimension', () => { + it('removes corresponding collapse function if exists', () => { + const state = getExampleState(); + + const colIds = ['1', '2', '3', '4']; + + state.layers[0].primaryGroups = colIds; + + state.layers[0].collapseFns = { + '1': 'sum', + '3': 'max', + }; + + const newState = pieVisualization.removeDimension({ + layerId: LAYER_ID, + columnId: '3', + prevState: state, + frame: mockFrame(), + }); + + expect(newState.layers[0].collapseFns).not.toHaveProperty('3'); + }); + }); + + describe('#getConfiguration', () => { + it('assigns correct icons to accessors', () => { + const colIds = ['1', '2', '3', '4']; + + const frame = mockFrame(); + frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => + colIds.map((id) => ({ columnId: id, fields: [] })); + + const state = getExampleState(); + state.layers[0].primaryGroups = colIds; + state.layers[0].collapseFns = { + '1': 'sum', + '3': 'max', + }; + const configuration = pieVisualization.getConfiguration({ + state, + frame, + layerId: state.layers[0].layerId, + }); + + // palette should be assigned to the first non-collapsed dimension + expect(configuration.groups[0].accessors).toMatchInlineSnapshot(` + Array [ + Object { + "columnId": "1", + "triggerIcon": "aggregate", + }, + Object { + "columnId": "2", + "palette": Array [ + "red", + "black", + ], + "triggerIcon": "colorBy", + }, + Object { + "columnId": "3", + "triggerIcon": "aggregate", + }, + Object { + "columnId": "4", + "triggerIcon": undefined, + }, + ] + `); + + const mosaicState = getExampleState(); + mosaicState.shape = PieChartTypes.MOSAIC; + mosaicState.layers[0].primaryGroups = colIds.slice(0, 2); + mosaicState.layers[0].secondaryGroups = colIds.slice(2); + mosaicState.layers[0].collapseFns = { + '1': 'sum', + '3': 'max', + }; + const mosaicConfiguration = pieVisualization.getConfiguration({ + state: mosaicState, + frame, + layerId: mosaicState.layers[0].layerId, + }); + + expect(mosaicConfiguration.groups.map(({ accessors }) => accessors)).toMatchInlineSnapshot(` + Array [ + Array [ + Object { + "columnId": "1", + "triggerIcon": "aggregate", + }, + Object { + "columnId": "2", + "palette": Array [ + "red", + "black", + ], + "triggerIcon": "colorBy", + }, + ], + Array [ + Object { + "columnId": "3", + "triggerIcon": "aggregate", + }, + Object { + "columnId": "4", + "triggerIcon": undefined, + }, + ], + Array [], + ] + `); + }); + + it("doesn't count collapsed columns toward the dimension limits", () => { + const colIds = new Array(PartitionChartsMeta.pie.maxBuckets) + .fill(undefined) + .map((_, i) => String(i + 1)); + + const frame = mockFrame(); + frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => + colIds.map((id) => ({ columnId: id, fields: [] })); + + const state = getExampleState(); + state.layers[0].primaryGroups = colIds; + + const getConfig = (_state: PieVisualizationState) => + pieVisualization.getConfiguration({ + state: _state, + frame, + layerId: state.layers[0].layerId, + }); + + expect(getConfig(state).groups[0].supportsMoreColumns).toBeFalsy(); + + const stateWithCollapsed = cloneDeep(state); + stateWithCollapsed.layers[0].collapseFns = { '1': 'sum' }; + + expect(getConfig(stateWithCollapsed).groups[0].supportsMoreColumns).toBeTruthy(); + }); + }); }); diff --git a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx index 49fc204fe5591f..6a58d46b34caab 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx @@ -13,6 +13,7 @@ import type { PaletteRegistry } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; +import { EuiSpacer } from '@elastic/eui'; import type { Visualization, OperationMetadata, @@ -45,18 +46,28 @@ const bucketedOperations = (op: OperationMetadata) => op.isBucketed; const numberMetricOperations = (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number' && !op.isStaticValue; +export const isCollapsed = (columnId: string, layer: PieLayerState) => + Boolean(layer.collapseFns?.[columnId]); + const applyPaletteToColumnConfig = ( columns: AccessorConfig[], - { palette }: PieVisualizationState, + layer: PieLayerState, + palette: PieVisualizationState['palette'], paletteService: PaletteRegistry ) => { - columns[0] = { - columnId: columns[0].columnId, - triggerIcon: 'colorBy', - palette: paletteService - .get(palette?.name || 'default') - .getCategoricalColors(10, palette?.params), - }; + const firstNonCollapsedColumnIdx = columns.findIndex( + (column) => !isCollapsed(column.columnId, layer) + ); + + if (firstNonCollapsedColumnIdx > -1) { + columns[firstNonCollapsedColumnIdx] = { + columnId: columns[firstNonCollapsedColumnIdx].columnId, + triggerIcon: 'colorBy', + palette: paletteService + .get(palette?.name || 'default') + .getCategoricalColors(10, palette?.params), + }; + } }; export const getPieVisualization = ({ @@ -129,10 +140,11 @@ export const getPieVisualization = ({ // When we add a column it could be empty, and therefore have no order const accessors: AccessorConfig[] = originalOrder.map((accessor) => ({ columnId: accessor, + triggerIcon: isCollapsed(accessor, layer) ? ('aggregate' as const) : undefined, })); if (accessors.length) { - applyPaletteToColumnConfig(accessors, state, paletteService); + applyPaletteToColumnConfig(accessors, layer, state.palette, paletteService); } const primaryGroupConfigBaseProps = { @@ -143,6 +155,11 @@ export const getPieVisualization = ({ filterOperations: bucketedOperations, }; + const totalNonCollapsedAccessors = accessors.reduce( + (total, { columnId }) => total + (isCollapsed(columnId, layer) ? 0 : 1), + 0 + ); + switch (state.shape) { case 'donut': case 'pie': @@ -154,7 +171,8 @@ export const getPieVisualization = ({ dimensionEditorGroupLabel: i18n.translate('xpack.lens.pie.sliceDimensionGroupLabel', { defaultMessage: 'Slice', }), - supportsMoreColumns: accessors.length < PartitionChartsMeta.pie.maxBuckets, + supportsMoreColumns: totalNonCollapsedAccessors < PartitionChartsMeta.pie.maxBuckets, + dimensionsTooMany: totalNonCollapsedAccessors - PartitionChartsMeta.pie.maxBuckets, dataTestSubj: 'lnsPie_sliceByDimensionPanel', }; case 'mosaic': @@ -166,7 +184,8 @@ export const getPieVisualization = ({ dimensionEditorGroupLabel: i18n.translate('xpack.lens.pie.verticalAxisDimensionLabel', { defaultMessage: 'Vertical axis', }), - supportsMoreColumns: accessors.length === 0, + supportsMoreColumns: totalNonCollapsedAccessors === 0, + dimensionsTooMany: totalNonCollapsedAccessors - 1, dataTestSubj: 'lnsPie_verticalAxisDimensionPanel', }; default: @@ -178,7 +197,10 @@ export const getPieVisualization = ({ dimensionEditorGroupLabel: i18n.translate('xpack.lens.pie.treemapDimensionGroupLabel', { defaultMessage: 'Group', }), - supportsMoreColumns: accessors.length < PartitionChartsMeta[state.shape].maxBuckets, + supportsMoreColumns: + totalNonCollapsedAccessors < PartitionChartsMeta[state.shape].maxBuckets, + dimensionsTooMany: + totalNonCollapsedAccessors - PartitionChartsMeta[state.shape].maxBuckets, dataTestSubj: 'lnsPie_groupByDimensionPanel', }; } @@ -188,6 +210,7 @@ export const getPieVisualization = ({ const originalSecondaryOrder = getSortedGroups(datasource, layer, 'secondaryGroups'); const accessors = originalSecondaryOrder.map((accessor) => ({ columnId: accessor, + triggerIcon: isCollapsed(accessor, layer) ? ('aggregate' as const) : undefined, })); const secondaryGroupConfigBaseProps = { @@ -198,6 +221,11 @@ export const getPieVisualization = ({ filterOperations: bucketedOperations, }; + const totalNonCollapsedAccessors = accessors.reduce( + (total, { columnId }) => total + (isCollapsed(columnId, layer) ? 0 : 1), + 0 + ); + switch (state.shape) { case 'mosaic': return { @@ -211,7 +239,8 @@ export const getPieVisualization = ({ defaultMessage: 'Horizontal axis', } ), - supportsMoreColumns: accessors.length === 0, + supportsMoreColumns: totalNonCollapsedAccessors === 0, + dimensionsTooMany: totalNonCollapsedAccessors - 1, dataTestSubj: 'lnsPie_horizontalAxisDimensionPanel', }; default: @@ -280,13 +309,21 @@ export const getPieVisualization = ({ return l; } - if (l.metric === columnId) { - return { ...l, metric: undefined }; + const newLayer = { ...l }; + + if (l.collapseFns?.[columnId]) { + const newCollapseFns = { ...l.collapseFns }; + delete newCollapseFns[columnId]; + newLayer.collapseFns = newCollapseFns; + } + + if (newLayer.metric === columnId) { + return { ...newLayer, metric: undefined }; } return { - ...l, - primaryGroups: l.primaryGroups.filter((c) => c !== columnId), - secondaryGroups: l.secondaryGroups?.filter((c) => c !== columnId) ?? undefined, + ...newLayer, + primaryGroups: newLayer.primaryGroups.filter((c) => c !== columnId), + secondaryGroups: newLayer.secondaryGroups?.filter((c) => c !== columnId) ?? undefined, }; }), }; @@ -386,7 +423,35 @@ export const getPieVisualization = ({ }, getErrorMessages(state) { - // not possible to break it? - return undefined; + const hasTooManyBucketDimensions = state.layers + .map( + (layer) => + Array.from(new Set([...layer.primaryGroups, ...(layer.secondaryGroups ?? [])])).filter( + (columnId) => !isCollapsed(columnId, layer) + ).length > PartitionChartsMeta[state.shape].maxBuckets + ) + .some(Boolean); + + return hasTooManyBucketDimensions + ? [ + { + shortMessage: i18n.translate('xpack.lens.pie.tooManyDimensions', { + defaultMessage: 'Your visualization has too many dimensions.', + }), + longMessage: ( + <span> + {i18n.translate('xpack.lens.pie.tooManyDimensionsLong', { + defaultMessage: + 'Your visualization has too many dimensions. Please follow the instructions in the layer panel.', + })} + <EuiSpacer size="s" /> + {i18n.translate('xpack.lens.pie.collapsedDimensionsDontCount', { + defaultMessage: "(Collapsed dimensions don't count toward this limit.)", + })} + </span> + ), + }, + ] + : []; }, }); From af3b8d4b5bc186f07bd624be6b490920d0ff50ff Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 12 Sep 2022 11:29:34 -0600 Subject: [PATCH 080/144] skip failing test suite (#140520) --- x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts b/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts index 480d07e7144f3c..7bcda35a892f95 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/edit_monitor.ts @@ -16,7 +16,8 @@ import { getFixtureJson } from './helper/get_fixture_json'; import { PrivateLocationTestService } from './services/private_location_test_service'; export default function ({ getService }: FtrProviderContext) { - describe('[PUT] /internal/uptime/service/monitors', function () { + // Failing: See https://github.com/elastic/kibana/issues/140520 + describe.skip('[PUT] /internal/uptime/service/monitors', function () { this.tags('skipCloud'); const supertest = getService('supertest'); From 3e47ce179d4311bba4284848ec125a65776c0dd5 Mon Sep 17 00:00:00 2001 From: Davis McPhee <davis.mcphee@elastic.co> Date: Mon, 12 Sep 2022 14:37:05 -0300 Subject: [PATCH 081/144] [Discover] Disable scripted filters on non-matching data views to avoid runtime errors when fetching (#137354) * [Discover] Ignore scripted filters on non-matching data views to avoid runtime errors on fetch * [Discover] Fix broken tests * [Discover] Add test for getApplicableFilters * [Discover] Update invalid scripted filter behaviour to disable filters instead of ignoring them * [Discover] Clean up scripted filter tests * [Discover] Continue working on fix for scripted filters * [Discover] Update get_valid_filters to disable all scripted filters that don't match the current data view * [Discover] Rollback changes to update data view IDs on filters * [Discover] Only update filters in discover_state.ts if they've changed Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../discover/public/__mocks__/services.ts | 2 + .../application/context/context_app.tsx | 2 +- .../context/hooks/use_context_app_state.ts | 12 ++++- .../context/services/context_state.test.ts | 2 + .../context/services/context_state.ts | 14 +++++- .../main/services/discover_state.ts | 9 ++++ .../public/utils/get_valid_filters.test.ts | 45 +++++++++++++++++++ .../public/utils/get_valid_filters.ts | 25 +++++++++++ 8 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 src/plugins/discover/public/utils/get_valid_filters.test.ts create mode 100644 src/plugins/discover/public/utils/get_valid_filters.ts diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index 9a466f6971c0bf..cd99577962aa46 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -29,6 +29,8 @@ import { dataViewsMock } from './data_views'; const dataPlugin = dataPluginMock.createStartContract(); const expressionsPlugin = expressionsPluginMock.createStartContract(); +dataPlugin.query.filterManager.getFilters = jest.fn(() => []); + export const discoverServiceMock = { core: coreMock.createStart(), chrome: chromeServiceMock.createStartContract(), diff --git a/src/plugins/discover/public/application/context/context_app.tsx b/src/plugins/discover/public/application/context/context_app.tsx index f44103f70b8ddf..b7e3f834781ccb 100644 --- a/src/plugins/discover/public/application/context/context_app.tsx +++ b/src/plugins/discover/public/application/context/context_app.tsx @@ -57,7 +57,7 @@ export const ContextApp = ({ dataView, anchorId }: ContextAppProps) => { /** * Context app state */ - const { appState, globalState, setAppState } = useContextAppState({ services }); + const { appState, globalState, setAppState } = useContextAppState({ services, dataView }); const prevAppState = useRef<AppState>(); const prevGlobalState = useRef<GlobalState>({ filters: [] }); diff --git a/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts b/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts index 594ef3d3ffd4c8..db6ba390f67a76 100644 --- a/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts +++ b/src/plugins/discover/public/application/context/hooks/use_context_app_state.ts @@ -5,13 +5,20 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import { DataView } from '@kbn/data-views-plugin/common'; import { useEffect, useMemo, useState } from 'react'; import { CONTEXT_DEFAULT_SIZE_SETTING } from '../../../../common'; import { DiscoverServices } from '../../../build_services'; import { AppState, getState, GlobalState } from '../services/context_state'; -export function useContextAppState({ services }: { services: DiscoverServices }) { +export function useContextAppState({ + services, + dataView, +}: { + services: DiscoverServices; + dataView: DataView; +}) { const { uiSettings: config, history, core } = services; const stateContainer = useMemo(() => { @@ -22,8 +29,9 @@ export function useContextAppState({ services }: { services: DiscoverServices }) toasts: core.notifications.toasts, uiSettings: config, data: services.data, + dataView, }); - }, [config, history, core.notifications.toasts, services.data]); + }, [config, history, core.notifications.toasts, services.data, dataView]); const [appState, setAppState] = useState<AppState>(stateContainer.appState.getState()); const [globalState, setGlobalState] = useState<GlobalState>( diff --git a/src/plugins/discover/public/application/context/services/context_state.test.ts b/src/plugins/discover/public/application/context/services/context_state.test.ts index a420b8d08e0b6d..2b071ad9f7fbd2 100644 --- a/src/plugins/discover/public/application/context/services/context_state.test.ts +++ b/src/plugins/discover/public/application/context/services/context_state.test.ts @@ -14,6 +14,7 @@ import { FilterManager } from '@kbn/data-plugin/public'; import { coreMock } from '@kbn/core/public/mocks'; import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../common'; import { discoverServiceMock } from '../../../__mocks__/services'; +import { dataViewMock } from '../../../__mocks__/data_view'; discoverServiceMock.data.query.filterManager.getAppFilters = jest.fn(() => []); discoverServiceMock.data.query.filterManager.getGlobalFilters = jest.fn(() => []); @@ -34,6 +35,7 @@ describe('Test Discover Context State', () => { (key === SEARCH_FIELDS_FROM_SOURCE ? true : ['_source']) as unknown as T, } as IUiSettingsClient, data: discoverServiceMock.data, + dataView: dataViewMock, }); state.startSync(); }); diff --git a/src/plugins/discover/public/application/context/services/context_state.ts b/src/plugins/discover/public/application/context/services/context_state.ts index 9739b5bc0fde49..8b41152496ec9f 100644 --- a/src/plugins/discover/public/application/context/services/context_state.ts +++ b/src/plugins/discover/public/application/context/services/context_state.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { cloneDeep, isEqual } from 'lodash'; +import { isEqual } from 'lodash'; import { History } from 'history'; import { NotificationsStart, IUiSettingsClient } from '@kbn/core/public'; import { Filter, compareFilters, COMPARE_ALL_OPTIONS, FilterStateStore } from '@kbn/es-query'; @@ -19,6 +19,8 @@ import { } from '@kbn/kibana-utils-plugin/public'; import { connectToQueryState, DataPublicPluginStart, FilterManager } from '@kbn/data-plugin/public'; +import { DataView } from '@kbn/data-views-plugin/common'; +import { getValidFilters } from '../../../utils/get_valid_filters'; import { handleSourceColumnState } from '../../../utils/state_helpers'; export interface AppState { @@ -83,6 +85,11 @@ export interface GetStateParams { * data service */ data: DataPublicPluginStart; + + /** + * the current data view + */ + dataView: DataView; } export interface GetStateReturn { @@ -134,6 +141,7 @@ export function getState({ toasts, uiSettings, data, + dataView, }: GetStateParams): GetStateReturn { const stateStorage = createKbnUrlStateStorage({ useHash: storeInSessionStorage, @@ -191,7 +199,9 @@ export function getState({ globalState: globalStateContainer, appState: appStateContainer, startSync: () => { - data.query.filterManager.setFilters(cloneDeep(getAllFilters())); + // some filters may not be valid for this context, so update + // the filter manager with a modified list of valid filters + data.query.filterManager.setFilters(getValidFilters(dataView, getAllFilters())); const stopSyncingAppFilters = connectToQueryState(data.query, appStateContainer, { filters: FilterStateStore.APP_STATE, diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts index 33393eeecdd758..568a219b952e77 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -42,6 +42,7 @@ import { handleSourceColumnState } from '../../../utils/state_helpers'; import { DISCOVER_APP_LOCATOR, DiscoverAppLocatorParams } from '../../../locator'; import { VIEW_MODE } from '../../../components/view_mode_toggle'; import { cleanupUrlState } from '../utils/cleanup_url_state'; +import { getValidFilters } from '../../../utils/get_valid_filters'; export interface AppState { /** @@ -319,6 +320,14 @@ export function getState({ stateStorage ); + // some filters may not be valid for this context, so update + // the filter manager with a modified list of valid filters + const currentFilters = filterManager.getFilters(); + const validFilters = getValidFilters(dataView, currentFilters); + if (!isEqual(currentFilters, validFilters)) { + filterManager.setFilters(validFilters); + } + const { start, stop } = syncAppState(); replaceUrlAppState({}).then(() => { diff --git a/src/plugins/discover/public/utils/get_valid_filters.test.ts b/src/plugins/discover/public/utils/get_valid_filters.test.ts new file mode 100644 index 00000000000000..feb9d58a23a32f --- /dev/null +++ b/src/plugins/discover/public/utils/get_valid_filters.test.ts @@ -0,0 +1,45 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataView } from '@kbn/data-views-plugin/common'; +import { getValidFilters } from './get_valid_filters'; + +describe('getValidFilters', () => { + const filter = (index: string, disabled: boolean, script: boolean) => ({ + meta: { + index, + disabled, + }, + ...(script ? { query: { script: {} } } : {}), + }); + const dataView = { + id: '123', + } as DataView; + + it("should only disable scripted fields that don't match the current data view", () => { + const filters = getValidFilters(dataView, [ + filter('123', false, false), + filter('123', true, false), + filter('123', false, true), + filter('123', true, true), + filter('321', false, false), + filter('321', true, false), + filter('321', false, true), + filter('321', true, true), + ]); + expect(filters.length).toBe(8); + expect(filters[0].meta.disabled).toBe(false); + expect(filters[1].meta.disabled).toBe(true); + expect(filters[2].meta.disabled).toBe(false); + expect(filters[3].meta.disabled).toBe(true); + expect(filters[4].meta.disabled).toBe(false); + expect(filters[5].meta.disabled).toBe(true); + expect(filters[6].meta.disabled).toBe(true); + expect(filters[7].meta.disabled).toBe(true); + }); +}); diff --git a/src/plugins/discover/public/utils/get_valid_filters.ts b/src/plugins/discover/public/utils/get_valid_filters.ts new file mode 100644 index 00000000000000..2d43262efc1968 --- /dev/null +++ b/src/plugins/discover/public/utils/get_valid_filters.ts @@ -0,0 +1,25 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataView } from '@kbn/data-views-plugin/common'; +import { Filter } from '@kbn/es-query'; + +export const getValidFilters = (dataView: DataView, filters: Filter[]): Filter[] => { + return filters.map((filter) => { + const meta = { ...filter.meta }; + + // We need to disable scripted filters that don't match this data view + // since we can't guarantee they'll succeed for the current data view + // and can lead to runtime errors + if (filter.query?.script && meta.index !== dataView.id) { + meta.disabled = true; + } + + return { ...filter, meta }; + }); +}; From 412cedb95f525a7026f7bd090f173eefde93cc39 Mon Sep 17 00:00:00 2001 From: Elastic Machine <elasticmachine@users.noreply.github.com> Date: Tue, 13 Sep 2022 03:12:34 +0930 Subject: [PATCH 082/144] [Fleet] Update kubernetes templates for elastic-agent (#140534) --- x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts b/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts index 90b2aa851fd522..f05441f3db1ff7 100644 --- a/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts +++ b/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts @@ -6,7 +6,7 @@ */ export const elasticAgentStandaloneManifest = `--- -# For more information refer to https://www.elastic.co/guide/en/fleet/current/running-on-kubernetes-standalone.html +# For more information refer https://www.elastic.co/guide/en/fleet/current/running-on-kubernetes-standalone.html apiVersion: apps/v1 kind: DaemonSet metadata: From e741176614c09354cd96f3feced7249a55326b02 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski <jon@elastic.co> Date: Mon, 12 Sep 2022 14:03:20 -0400 Subject: [PATCH 083/144] [cft] Temporarily disable cloud deployments (#140538) * [cft] Temporarily disable cloud deployments * annotation --- .buildkite/scripts/steps/cloud/build_and_deploy.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.buildkite/scripts/steps/cloud/build_and_deploy.sh b/.buildkite/scripts/steps/cloud/build_and_deploy.sh index 017e25bb288508..f9b2a3fc928d2e 100755 --- a/.buildkite/scripts/steps/cloud/build_and_deploy.sh +++ b/.buildkite/scripts/steps/cloud/build_and_deploy.sh @@ -2,6 +2,14 @@ set -euo pipefail +echo "Cloud deployments have been temporarily disabled. We're investigating, status updates will be posted in #kibana-operations." +cat << EOF | buildkite-agent annotate --style "error" --context cloud + ### Cloud Deployment + + Cloud deployments have been temporarily disabled. We're investigating, status updates will be posted in #kibana-operations. +EOF +exit 0 + source .buildkite/scripts/common/util.sh .buildkite/scripts/bootstrap.sh From 636b67da401ac26ab74c4dc3a892d1777f86b83a Mon Sep 17 00:00:00 2001 From: Dominique Clarke <dominique.clarke@elastic.co> Date: Mon, 12 Sep 2022 14:09:42 -0400 Subject: [PATCH 084/144] synthetics - project monitors - skip editing if monitor hasn't been edited (#140094) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../synthetics_service/project_monitor_formatter.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.ts index c96b06886a3060..b9fe8fafdfc089 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor_formatter.ts @@ -258,15 +258,14 @@ export class ProjectMonitorFormatter { attributes: { [ConfigKey.REVISION]: _, ...normalizedPreviousMonitorAttributes }, } = normalizeSecrets(decryptedPreviousMonitor); const hasMonitorBeenEdited = !isEqual(normalizedMonitor, normalizedPreviousMonitorAttributes); - const monitorWithRevision = formatSecrets({ - ...normalizedPreviousMonitorAttributes, // ensures monitor AAD remains consistent in the event of field name changes - ...normalizedMonitor, - revision: hasMonitorBeenEdited - ? (previousMonitor.attributes[ConfigKey.REVISION] || 0) + 1 - : previousMonitor.attributes[ConfigKey.REVISION], - }); if (hasMonitorBeenEdited) { + const monitorWithRevision = formatSecrets({ + ...normalizedPreviousMonitorAttributes, + ...normalizedMonitor, + revision: (previousMonitor.attributes[ConfigKey.REVISION] || 0) + 1, + }); + const { editedMonitor } = await syncEditedMonitor({ normalizedMonitor, monitorWithRevision, From a0df48362b642ed286f852bf500c55be5ba2dc18 Mon Sep 17 00:00:00 2001 From: Bhavya RM <bhavya@elastic.co> Date: Mon, 12 Sep 2022 15:23:16 -0400 Subject: [PATCH 085/144] Timepicker refactoring of anomaly_charts_dashboard_embeddables.ts (#140337) --- .../anomaly_charts_dashboard_embeddables.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_charts_dashboard_embeddables.ts b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_charts_dashboard_embeddables.ts index 0cb95109df068d..f2273b168489b6 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_charts_dashboard_embeddables.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection_integrations/anomaly_charts_dashboard_embeddables.ts @@ -32,6 +32,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); const PageObjects = getPageObjects(['common', 'timePicker', 'dashboard']); + const from = 'Feb 7, 2016 @ 00:00:00.000'; + const to = 'Feb 11, 2016 @ 00:00:00.000'; describe('anomaly charts in dashboard', function () { this.tags(['ml']); @@ -41,11 +43,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); await ml.testResources.setKibanaTimeZoneToUTC(); await ml.securityUI.loginAsMlPowerUser(); + await PageObjects.common.setTime({ from, to }); }); after(async () => { await ml.api.cleanMlIndices(); await ml.testResources.deleteIndexPatternByTitle('ft_farequote'); + await PageObjects.common.unsetTime(); }); for (const testData of testDataList) { @@ -80,13 +84,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('create new anomaly charts panel', async () => { await ml.dashboardEmbeddables.clickInitializerConfirmButtonEnabled(); await ml.dashboardEmbeddables.assertDashboardPanelExists(testData.panelTitle); - - await ml.dashboardEmbeddables.assertNoMatchingAnomaliesMessageExists(); - - await PageObjects.timePicker.setAbsoluteRange( - 'Feb 7, 2016 @ 00:00:00.000', - 'Feb 11, 2016 @ 00:00:00.000' - ); await PageObjects.timePicker.pauseAutoRefresh(); await ml.dashboardEmbeddables.assertAnomalyChartsSeverityThresholdControlExists(); await ml.dashboardEmbeddables.assertAnomalyChartsExists(); From 44ab700f3d713bb7eee1f33f3ef26a48b2b217aa Mon Sep 17 00:00:00 2001 From: Tyler Smalley <tyler.smalley@elastic.co> Date: Mon, 12 Sep 2022 13:08:52 -0700 Subject: [PATCH 086/144] Removes Percy based visual regression tests (#139252) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Jonathan Budzenski <jon@elastic.co> --- .buildkite/ftr_configs.yml | 2 - .eslintrc.js | 1 - .github/CODEOWNERS | 1 - package.json | 1 - test/visual_regression/config.ts | 30 - .../visual_regression/ftr_provider_context.ts | 15 - test/visual_regression/services/index.ts | 15 - .../services/visual_testing/index.ts | 9 - .../visual_testing/take_percy_snapshot.js | 102 --- .../services/visual_testing/visual_testing.ts | 114 ---- test/visual_regression/tests/console_app.ts | 71 -- .../tests/discover/chart_visualization.ts | 117 ---- .../visual_regression/tests/discover/index.ts | 25 - test/visual_regression/tests/vega/index.ts | 25 - .../tests/vega/vega_map_visualization.ts | 39 -- x-pack/test/visual_regression/config.ts | 31 - .../ftr_provider_context.d.ts | 13 - x-pack/test/visual_regression/page_objects.ts | 10 - x-pack/test/visual_regression/services.ts | 14 - .../tests/canvas/fullscreen.js | 25 - .../visual_regression/tests/canvas/index.js | 30 - .../visual_regression/tests/infra/index.js | 19 - .../tests/infra/saved_views.js | 87 --- .../tests/infra/waffle_map.js | 27 - .../visual_regression/tests/login_page.ts | 58 -- .../visual_regression/tests/maps/index.js | 61 -- .../tests/maps/vector_styling.js | 49 -- yarn.lock | 635 ++++++------------ 28 files changed, 190 insertions(+), 1436 deletions(-) delete mode 100644 test/visual_regression/config.ts delete mode 100644 test/visual_regression/ftr_provider_context.ts delete mode 100644 test/visual_regression/services/index.ts delete mode 100644 test/visual_regression/services/visual_testing/index.ts delete mode 100644 test/visual_regression/services/visual_testing/take_percy_snapshot.js delete mode 100644 test/visual_regression/services/visual_testing/visual_testing.ts delete mode 100644 test/visual_regression/tests/console_app.ts delete mode 100644 test/visual_regression/tests/discover/chart_visualization.ts delete mode 100644 test/visual_regression/tests/discover/index.ts delete mode 100644 test/visual_regression/tests/vega/index.ts delete mode 100644 test/visual_regression/tests/vega/vega_map_visualization.ts delete mode 100644 x-pack/test/visual_regression/config.ts delete mode 100644 x-pack/test/visual_regression/ftr_provider_context.d.ts delete mode 100644 x-pack/test/visual_regression/page_objects.ts delete mode 100644 x-pack/test/visual_regression/services.ts delete mode 100644 x-pack/test/visual_regression/tests/canvas/fullscreen.js delete mode 100644 x-pack/test/visual_regression/tests/canvas/index.js delete mode 100644 x-pack/test/visual_regression/tests/infra/index.js delete mode 100644 x-pack/test/visual_regression/tests/infra/saved_views.js delete mode 100644 x-pack/test/visual_regression/tests/infra/waffle_map.js delete mode 100644 x-pack/test/visual_regression/tests/login_page.ts delete mode 100644 x-pack/test/visual_regression/tests/maps/index.js delete mode 100644 x-pack/test/visual_regression/tests/maps/vector_styling.js diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index ffd9b63271d5f0..561f783e917ddd 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -45,8 +45,6 @@ disabled: - x-pack/plugins/observability/e2e/synthetics_run.ts # Configs that exist but weren't running in CI when this file was introduced - - test/visual_regression/config.ts - - x-pack/test/visual_regression/config.ts - x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/config.ts - x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/config.ts - x-pack/test/alerting_api_integration/spaces_only_legacy/config.ts diff --git a/.eslintrc.js b/.eslintrc.js index 406e58e17d7a6e..da5dfb4eccb5d6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -593,7 +593,6 @@ module.exports = { 'test/*/config_open.ts', 'test/*/*.config.ts', 'test/*/{tests,test_suites,apis,apps}/**/*', - 'test/visual_regression/tests/**/*', 'x-pack/test/*/{tests,test_suites,apis,apps}/**/*', 'x-pack/test/*/*config.*ts', 'x-pack/test/saved_object_api_integration/*/apis/**/*', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cebe65017c984c..9df9f99c02adc1 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -221,7 +221,6 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/test/api_integration/apis/maps/ @elastic/kibana-gis /x-pack/test/functional/apps/maps/ @elastic/kibana-gis /x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis -/x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis /x-pack/plugins/stack_alerts/server/alert_types/geo_containment @elastic/kibana-gis /x-pack/plugins/stack_alerts/public/alert_types/geo_containment @elastic/kibana-gis #CC# /x-pack/plugins/file_upload @elastic/kibana-gis diff --git a/package.json b/package.json index e53f8ed64b06b1..41e22f2320ba7a 100644 --- a/package.json +++ b/package.json @@ -722,7 +722,6 @@ "@mapbox/vector-tile": "1.3.1", "@octokit/rest": "^16.35.0", "@openpgp/web-stream-tools": "^0.0.10", - "@percy/agent": "^0.28.6", "@storybook/addon-a11y": "^6.4.22", "@storybook/addon-actions": "^6.4.22", "@storybook/addon-controls": "^6.4.22", diff --git a/test/visual_regression/config.ts b/test/visual_regression/config.ts deleted file mode 100644 index 294848246e7c85..00000000000000 --- a/test/visual_regression/config.ts +++ /dev/null @@ -1,30 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FtrConfigProviderContext } from '@kbn/test'; -import { services } from './services'; - -export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); - - return { - ...functionalConfig.getAll(), - - testFiles: [ - require.resolve('./tests/console_app'), - require.resolve('./tests/discover'), - require.resolve('./tests/vega'), - ], - - services, - - junit: { - reportName: 'Kibana Visual Regression Tests', - }, - }; -} diff --git a/test/visual_regression/ftr_provider_context.ts b/test/visual_regression/ftr_provider_context.ts deleted file mode 100644 index 28bedd1ca6bc34..00000000000000 --- a/test/visual_regression/ftr_provider_context.ts +++ /dev/null @@ -1,15 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { GenericFtrProviderContext, GenericFtrService } from '@kbn/test'; - -import { pageObjects } from '../functional/page_objects'; -import { services } from './services'; - -export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>; -export class FtrService extends GenericFtrService<FtrProviderContext> {} diff --git a/test/visual_regression/services/index.ts b/test/visual_regression/services/index.ts deleted file mode 100644 index 9aefe1f8de7809..00000000000000 --- a/test/visual_regression/services/index.ts +++ /dev/null @@ -1,15 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { services as functionalServices } from '../../functional/services'; -import { VisualTestingService } from './visual_testing'; - -export const services = { - ...functionalServices, - visualTesting: VisualTestingService, -}; diff --git a/test/visual_regression/services/visual_testing/index.ts b/test/visual_regression/services/visual_testing/index.ts deleted file mode 100644 index 156e3814d8a1d0..00000000000000 --- a/test/visual_regression/services/visual_testing/index.ts +++ /dev/null @@ -1,9 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export * from './visual_testing'; diff --git a/test/visual_regression/services/visual_testing/take_percy_snapshot.js b/test/visual_regression/services/visual_testing/take_percy_snapshot.js deleted file mode 100644 index 5325765c8d06bc..00000000000000 --- a/test/visual_regression/services/visual_testing/take_percy_snapshot.js +++ /dev/null @@ -1,102 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { readFileSync } from 'fs'; -import { agentJsFilename } from '@percy/agent/dist/utils/sdk-utils'; - -export function takePercySnapshot(show, hide) { - if (!window.PercyAgent) { - return false; - } - - // add percy styles to hide/show specific elements - const styleElement = document.createElement('style'); - styleElement.appendChild( - document.createTextNode(` - .hideInPercy { - visibility: hidden; - - .showInPercy { - visibility: visible; - } - } - - .showInPercy { - visibility: visible; - - .hideInPercy { - visibility: hidden; - } - } - `) - ); - document.head.appendChild(styleElement); - - const add = (selectors, className) => { - for (const selector of selectors) { - for (const element of document.querySelectorAll(selector)) { - element.classList.add(className); - } - } - }; - - const remove = (selectors, className) => { - for (const selector of selectors) { - for (const element of document.querySelectorAll(selector)) { - element.classList.remove(className); - } - } - }; - - // set Percy visibility on elements - add(hide, 'hideInPercy'); - if (show.length > 0) { - // hide the body by default - add(['body'], 'hideInPercy'); - add(show, 'showInPercy'); - } - - // convert canvas elements into static images - const replacements = []; - for (const canvas of document.querySelectorAll('canvas')) { - const image = document.createElement('img'); - image.classList.value = canvas.classList.value; - image.src = canvas.toDataURL(); - image.style.cssText = window.getComputedStyle(canvas).cssText; - canvas.parentElement.replaceChild(image, canvas); - replacements.push({ canvas, image }); - } - - try { - const agent = new window.PercyAgent({ - handleAgentCommunication: false, - }); - - // cache the dom snapshot containing the images - return agent.snapshot(document, { - widths: [document.documentElement.clientWidth], - }); - } finally { - // restore replaced canvases - for (const { image, canvas } of replacements) { - image.parentElement.replaceChild(canvas, image); - } - - // restore element visibility - document.head.removeChild(styleElement); - remove(['body'], 'hideInPercy'); - remove(show, 'showInPercy'); - remove(hide, 'hideInPercy'); - } -} - -export const takePercySnapshotWithAgent = ` - ${readFileSync(agentJsFilename(), 'utf8')} - - return (${takePercySnapshot.toString()}).apply(null, arguments); -`; diff --git a/test/visual_regression/services/visual_testing/visual_testing.ts b/test/visual_regression/services/visual_testing/visual_testing.ts deleted file mode 100644 index 59c601e6a2b6e6..00000000000000 --- a/test/visual_regression/services/visual_testing/visual_testing.ts +++ /dev/null @@ -1,114 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { postSnapshot } from '@percy/agent/dist/utils/sdk-utils'; -import testSubjSelector from '@kbn/test-subj-selector'; -import { Test } from '@kbn/test'; -import { kibanaPackageJson as pkg } from '@kbn/utils'; -import { FtrService, FtrProviderContext } from '../../ftr_provider_context'; - -// @ts-ignore internal js that is passed to the browser as is -import { takePercySnapshot, takePercySnapshotWithAgent } from './take_percy_snapshot'; - -export const DEFAULT_OPTIONS = { - widths: [1200], -}; - -export interface SnapshotOptions { - /** - * name to append to visual test name - */ - name?: string; - /** - * test subject selectiors to __show__ in screenshot - */ - show?: string[]; - /** - * test subject selectiors to __hide__ in screenshot - */ - hide?: string[]; -} - -const statsCache = new WeakMap<Test, { snapshotCount: number }>(); - -function getStats(test: Test) { - if (!statsCache.has(test)) { - statsCache.set(test, { - snapshotCount: 0, - }); - } - - return statsCache.get(test)!; -} - -export class VisualTestingService extends FtrService { - private readonly browser = this.ctx.getService('browser'); - private readonly log = this.ctx.getService('log'); - - private currentTest: Test | undefined; - - constructor(ctx: FtrProviderContext) { - super(ctx); - - this.ctx.getService('lifecycle').beforeEachTest.add((test) => { - this.currentTest = test; - }); - } - - public async snapshot(options: SnapshotOptions = {}) { - if (process.env.DISABLE_VISUAL_TESTING) { - this.log.warning( - 'Capturing of percy snapshots disabled, would normally capture a snapshot here!' - ); - return; - } - - this.log.debug('Capturing percy snapshot'); - - if (!this.currentTest) { - throw new Error('unable to determine current test'); - } - - const [domSnapshot, url] = await Promise.all([ - this.getSnapshot(options.show, options.hide), - this.browser.getCurrentUrl(), - ]); - const stats = getStats(this.currentTest); - stats.snapshotCount += 1; - - const { name } = options; - const success = await postSnapshot({ - name: `${this.currentTest.fullTitle()} [${name ? name : stats.snapshotCount}]`, - url, - domSnapshot, - clientInfo: `kibana-ftr:${pkg.version}`, - ...DEFAULT_OPTIONS, - }); - - if (!success) { - throw new Error('Percy snapshot failed'); - } - } - - private async getSnapshot(show: string[] = [], hide: string[] = []) { - const showSelectors = show.map(testSubjSelector); - const hideSelectors = hide.map(testSubjSelector); - const snapshot = await this.browser.execute<[string[], string[]], string | false>( - takePercySnapshot, - showSelectors, - hideSelectors - ); - return snapshot !== false - ? snapshot - : await this.browser.execute<[string[], string[]], string>( - takePercySnapshotWithAgent, - showSelectors, - hideSelectors - ); - } -} diff --git a/test/visual_regression/tests/console_app.ts b/test/visual_regression/tests/console_app.ts deleted file mode 100644 index 2c2351b76ad4f9..00000000000000 --- a/test/visual_regression/tests/console_app.ts +++ /dev/null @@ -1,71 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../ftr_provider_context'; - -const DEFAULT_REQUEST = ` - -GET _search -{ - "query": { - "match_all": {} - } -} - -`.trim(); - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const retry = getService('retry'); - const log = getService('log'); - const visualTesting = getService('visualTesting'); - const PageObjects = getPageObjects(['common', 'console']); - - describe.skip('console app', function describeIndexTests() { - before(async () => { - log.debug('navigateTo console'); - await PageObjects.common.navigateToApp('console'); - }); - - it('should show the default request', async () => { - // collapse the help pane because we only get the VISIBLE TEXT, not the part that is scrolled - await PageObjects.console.collapseHelp(); - await retry.try(async () => { - const actualRequest = await PageObjects.console.getRequest(); - log.debug(actualRequest); - expect(actualRequest.trim()).to.eql(DEFAULT_REQUEST); - }); - - await visualTesting.snapshot(); - }); - - it('default request response should include `"timed_out" : false`', async () => { - const expectedResponseContains = '"timed_out" : false,'; - await PageObjects.console.clickPlay(); - await retry.try(async () => { - const actualResponse = await PageObjects.console.getResponse(); - log.debug(actualResponse); - expect(actualResponse).to.contain(expectedResponseContains); - }); - }); - - it('settings should allow changing the text size', async () => { - await PageObjects.console.setFontSizeSetting(20); - await retry.try(async () => { - // the settings are not applied synchronously, so we retry for a time - expect(await PageObjects.console.getRequestFontSize()).to.be('20px'); - }); - - await PageObjects.console.setFontSizeSetting(24); - await retry.try(async () => { - // the settings are not applied synchronously, so we retry for a time - expect(await PageObjects.console.getRequestFontSize()).to.be('24px'); - }); - }); - }); -} diff --git a/test/visual_regression/tests/discover/chart_visualization.ts b/test/visual_regression/tests/discover/chart_visualization.ts deleted file mode 100644 index f8390064732b90..00000000000000 --- a/test/visual_regression/tests/discover/chart_visualization.ts +++ /dev/null @@ -1,117 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const retry = getService('retry'); - const esArchiver = getService('esArchiver'); - const browser = getService('browser'); - const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']); - const visualTesting = getService('visualTesting'); - const defaultSettings = { - defaultIndex: 'logstash-*', - 'discover:sampleSize': 1, - }; - - describe('discover', function describeIndexTests() { - before(async function () { - await kibanaServer.savedObjects.cleanStandardList(); - await kibanaServer.importExport.load( - 'test/functional/fixtures/kbn_archiver/discover/visual_regression' - ); - - // and load a set of makelogs data - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); - await kibanaServer.uiSettings.replace(defaultSettings); - await PageObjects.common.navigateToApp('discover'); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - }); - - after(async function unloadMakelogs() { - await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); - await kibanaServer.savedObjects.cleanStandardList(); - }); - - async function refreshDiscover() { - await browser.refresh(); - await PageObjects.header.awaitKibanaChrome(); - await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); - await PageObjects.discover.waitUntilSearchingHasFinished(); - await PageObjects.discover.waitForChartLoadingComplete(1); - } - - async function takeSnapshot() { - await refreshDiscover(); - await visualTesting.snapshot({ - show: ['discoverChart'], - }); - } - - describe('query', function () { - this.tags(['skipFirefox']); - - it('should show bars in the correct time zone', async function () { - await PageObjects.header.awaitGlobalLoadingIndicatorHidden(); - await PageObjects.discover.waitUntilSearchingHasFinished(); - await takeSnapshot(); - }); - - it('should show correct data for chart interval Hour', async function () { - await PageObjects.discover.setChartInterval('Hour'); - await takeSnapshot(); - }); - - it('should show correct data for chart interval Day', async function () { - await PageObjects.discover.setChartInterval('Day'); - await takeSnapshot(); - }); - - it('should show correct data for chart interval Week', async function () { - await PageObjects.discover.setChartInterval('Week'); - await takeSnapshot(); - }); - - it('browser back button should show previous interval Day', async function () { - await browser.goBack(); - await retry.try(async function tryingForTime() { - const actualInterval = await PageObjects.discover.getChartInterval(); - expect(actualInterval).to.be('Day'); - }); - await takeSnapshot(); - }); - - it('should show correct data for chart interval Month', async function () { - await PageObjects.discover.setChartInterval('Month'); - await takeSnapshot(); - }); - - it('should show correct data for chart interval Year', async function () { - await PageObjects.discover.setChartInterval('Year'); - await takeSnapshot(); - }); - - it('should show correct data for chart interval Auto', async function () { - await PageObjects.discover.setChartInterval('Auto'); - await takeSnapshot(); - }); - }); - - describe('time zone switch', () => { - it('should show bars in the correct time zone after switching', async function () { - await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'America/Phoenix' }); - await refreshDiscover(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await takeSnapshot(); - }); - }); - }); -} diff --git a/test/visual_regression/tests/discover/index.ts b/test/visual_regression/tests/discover/index.ts deleted file mode 100644 index 9142a430f963ba..00000000000000 --- a/test/visual_regression/tests/discover/index.ts +++ /dev/null @@ -1,25 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { DEFAULT_OPTIONS } from '../../services/visual_testing/visual_testing'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -// Width must be the same as visual_testing or canvas image widths will get skewed -const [SCREEN_WIDTH] = DEFAULT_OPTIONS.widths || []; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const browser = getService('browser'); - - describe('discover app', function () { - before(function () { - return browser.setWindowSize(SCREEN_WIDTH, 1000); - }); - - loadTestFile(require.resolve('./chart_visualization')); - }); -} diff --git a/test/visual_regression/tests/vega/index.ts b/test/visual_regression/tests/vega/index.ts deleted file mode 100644 index 9ab4e199439a4d..00000000000000 --- a/test/visual_regression/tests/vega/index.ts +++ /dev/null @@ -1,25 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { DEFAULT_OPTIONS } from '../../services/visual_testing/visual_testing'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -// Width must be the same as visual_testing or canvas image widths will get skewed -const [SCREEN_WIDTH] = DEFAULT_OPTIONS.widths || []; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const browser = getService('browser'); - - describe('vega app', function () { - before(function () { - return browser.setWindowSize(SCREEN_WIDTH, 1000); - }); - - loadTestFile(require.resolve('./vega_map_visualization')); - }); -} diff --git a/test/visual_regression/tests/vega/vega_map_visualization.ts b/test/visual_regression/tests/vega/vega_map_visualization.ts deleted file mode 100644 index d891e7f2bab6b0..00000000000000 --- a/test/visual_regression/tests/vega/vega_map_visualization.ts +++ /dev/null @@ -1,39 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['common', 'visualize', 'visChart', 'visEditor', 'vegaChart']); - const visualTesting = getService('visualTesting'); - - describe('vega chart in visualize app', () => { - before(async () => { - await esArchiver.loadIfNeeded( - 'test/functional/fixtures/es_archiver/kibana_sample_data_flights' - ); - await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/visualize.json'); - }); - - after(async () => { - await esArchiver.unload('test/functional/fixtures/es_archiver/kibana_sample_data_flights'); - await kibanaServer.importExport.unload( - 'test/functional/fixtures/kbn_archiver/visualize.json' - ); - }); - - it('should show map with vega layer', async function () { - await PageObjects.visualize.gotoVisualizationLandingPage(); - await PageObjects.visualize.openSavedVisualization('VegaMap'); - await PageObjects.visChart.waitForVisualizationRenderingStabilized(); - await visualTesting.snapshot(); - }); - }); -} diff --git a/x-pack/test/visual_regression/config.ts b/x-pack/test/visual_regression/config.ts deleted file mode 100644 index c7f0d8203833e2..00000000000000 --- a/x-pack/test/visual_regression/config.ts +++ /dev/null @@ -1,31 +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 { FtrConfigProviderContext } from '@kbn/test'; - -import { services } from './services'; - -export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); - - return { - ...functionalConfig.getAll(), - - testFiles: [ - require.resolve('./tests/canvas'), - require.resolve('./tests/login_page'), - require.resolve('./tests/maps'), - require.resolve('./tests/infra'), - ], - - services, - - junit: { - reportName: 'X-Pack Visual Regression Tests', - }, - }; -} diff --git a/x-pack/test/visual_regression/ftr_provider_context.d.ts b/x-pack/test/visual_regression/ftr_provider_context.d.ts deleted file mode 100644 index 24f5087ef7fe2f..00000000000000 --- a/x-pack/test/visual_regression/ftr_provider_context.d.ts +++ /dev/null @@ -1,13 +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 { GenericFtrProviderContext } from '@kbn/test'; - -import { pageObjects } from './page_objects'; -import { services } from './services'; - -export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>; diff --git a/x-pack/test/visual_regression/page_objects.ts b/x-pack/test/visual_regression/page_objects.ts deleted file mode 100644 index c8b0c9050dbb9c..00000000000000 --- a/x-pack/test/visual_regression/page_objects.ts +++ /dev/null @@ -1,10 +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 { pageObjects } from '../functional/page_objects'; - -export { pageObjects }; diff --git a/x-pack/test/visual_regression/services.ts b/x-pack/test/visual_regression/services.ts deleted file mode 100644 index 7d58bd3f35b324..00000000000000 --- a/x-pack/test/visual_regression/services.ts +++ /dev/null @@ -1,14 +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 { services as ossVisualRegressionServices } from '../../../test/visual_regression/services'; -import { services as functionalServices } from '../functional/services'; - -export const services = { - ...functionalServices, - visualTesting: ossVisualRegressionServices.visualTesting, -}; diff --git a/x-pack/test/visual_regression/tests/canvas/fullscreen.js b/x-pack/test/visual_regression/tests/canvas/fullscreen.js deleted file mode 100644 index 6a20db5bccdec4..00000000000000 --- a/x-pack/test/visual_regression/tests/canvas/fullscreen.js +++ /dev/null @@ -1,25 +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. - */ - -export default function ({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['common', 'canvas']); - const visualTesting = getService('visualTesting'); - - describe('fullscreen', () => { - it('workpad should display properly in fullscreen mode', async () => { - await PageObjects.common.navigateToApp('canvas', { - hash: '/workpad/workpad-1705f884-6224-47de-ba49-ca224fe6ec31/page/1', - }); - - await PageObjects.canvas.enterFullscreen(); - - await PageObjects.canvas.waitForWorkpadElements(); - - await visualTesting.snapshot(); - }); - }); -} diff --git a/x-pack/test/visual_regression/tests/canvas/index.js b/x-pack/test/visual_regression/tests/canvas/index.js deleted file mode 100644 index 20a262fef10fee..00000000000000 --- a/x-pack/test/visual_regression/tests/canvas/index.js +++ /dev/null @@ -1,30 +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 { DEFAULT_OPTIONS } from '../../../../../test/visual_regression/services/visual_testing/visual_testing'; - -const [SCREEN_WIDTH] = DEFAULT_OPTIONS.widths || []; - -export default function ({ loadTestFile, getService }) { - const esArchiver = getService('esArchiver'); - const browser = getService('browser'); - - describe('canvas app visual regression', function () { - before(async () => { - await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); - await esArchiver.load('x-pack/test/functional/es_archives/canvas/default'); - - await browser.setWindowSize(SCREEN_WIDTH, 1000); - }); - - after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/canvas/default'); - }); - - loadTestFile(require.resolve('./fullscreen')); - }); -} diff --git a/x-pack/test/visual_regression/tests/infra/index.js b/x-pack/test/visual_regression/tests/infra/index.js deleted file mode 100644 index 13669c50953f9a..00000000000000 --- a/x-pack/test/visual_regression/tests/infra/index.js +++ /dev/null @@ -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. - */ - -export default function ({ loadTestFile, getService }) { - const browser = getService('browser'); - - describe.skip('InfraUI Visual Regression', function () { - before(async () => { - await browser.setWindowSize(1600, 1000); - }); - - loadTestFile(require.resolve('./waffle_map')); - loadTestFile(require.resolve('./saved_views')); - }); -} diff --git a/x-pack/test/visual_regression/tests/infra/saved_views.js b/x-pack/test/visual_regression/tests/infra/saved_views.js deleted file mode 100644 index a2fb3fda206dab..00000000000000 --- a/x-pack/test/visual_regression/tests/infra/saved_views.js +++ /dev/null @@ -1,87 +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 { DATES } from '../../../functional/apps/infra/constants'; -const DATE_WITH_DATA = DATES.metricsAndLogs.hosts.withData; - -export default function ({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['common', 'infraHome', 'infraMetricsExplorer']); - const visualTesting = getService('visualTesting'); - const esArchiver = getService('esArchiver'); - - describe('saved views', () => { - before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - describe('Inverntory Test save functionality', () => { - it('should have save and load controls', async () => { - await PageObjects.common.navigateToApp('infraOps'); - await PageObjects.infraHome.goToTime(DATE_WITH_DATA); - await PageObjects.infraHome.getSaveViewButton(); - await PageObjects.infraHome.getLoadViewsButton(); - await visualTesting.snapshot(); - }); - - it('should open flyout list', async () => { - await PageObjects.infraHome.openSaveViewsFlyout(); - await visualTesting.snapshot(); - await PageObjects.infraHome.closeSavedViewFlyout(); - }); - - it('should open saved view modal', async () => { - await PageObjects.infraHome.openCreateSaveViewModal(); - await visualTesting.snapshot(); - }); - - it('should be able to enter a view name', async () => { - await PageObjects.infraHome.openEnterViewNameAndSave(); - await visualTesting.snapshot(); - }); - - it('should see a saved view in list', async () => { - await PageObjects.infraHome.openSaveViewsFlyout(); - await visualTesting.snapshot(); - }); - }); - - describe('Metric Explorer Test Saved Views', () => { - before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - describe('save functionality', () => { - it('should have saved views component', async () => { - await PageObjects.common.navigateToApp('infraOps'); - await PageObjects.infraHome.goToMetricExplorer(); - await PageObjects.infraSavedViews.getSavedViewsButton(); - await PageObjects.infraSavedViews.ensureViewIsLoaded('Default view'); - await visualTesting.snapshot(); - }); - - it('should open popover', async () => { - await PageObjects.infraSavedViews.clickSavedViewsButton(); - await visualTesting.snapshot(); - await PageObjects.infraSavedViews.closeSavedViewsPopover(); - }); - - it('should create new saved view and load it', async () => { - await PageObjects.infraSavedViews.clickSavedViewsButton(); - await PageObjects.infraSavedViews.clickSaveNewViewButton(); - await PageObjects.infraSavedViews.getCreateSavedViewModal(); - await PageObjects.infraSavedViews.createNewSavedView('view1'); - await PageObjects.infraSavedViews.ensureViewIsLoaded('view1'); - await visualTesting.snapshot(); - }); - - it('should new views should be listed in the load views list', async () => { - await PageObjects.infraSavedViews.clickSavedViewsButton(); - await PageObjects.infraSavedViews.clickLoadViewButton(); - await PageObjects.infraSavedViews.ensureViewIsLoadable('view1'); - await visualTesting.snapshot(); - await PageObjects.infraSavedViews.closeSavedViewsLoadModal(); - }); - }); - }); - }); -} diff --git a/x-pack/test/visual_regression/tests/infra/waffle_map.js b/x-pack/test/visual_regression/tests/infra/waffle_map.js deleted file mode 100644 index 70aaf89a059eb0..00000000000000 --- a/x-pack/test/visual_regression/tests/infra/waffle_map.js +++ /dev/null @@ -1,27 +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 { DATES } from '../../../functional/apps/infra/constants'; -const DATE_WITH_DATA = DATES.metricsAndLogs.hosts.withData; - -export default function ({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['common', 'infraHome']); - const visualTesting = getService('visualTesting'); - const esArchiver = getService('esArchiver'); - - describe('waffle map', () => { - before(() => esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - after(() => esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs')); - - it('should just work', async () => { - await PageObjects.common.navigateToApp('infraOps'); - await PageObjects.infraHome.goToTime(DATE_WITH_DATA); - await PageObjects.infraHome.getWaffleMap(); - await visualTesting.snapshot(); - }); - }); -} diff --git a/x-pack/test/visual_regression/tests/login_page.ts b/x-pack/test/visual_regression/tests/login_page.ts deleted file mode 100644 index 3e2b4100240361..00000000000000 --- a/x-pack/test/visual_regression/tests/login_page.ts +++ /dev/null @@ -1,58 +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 { FtrProviderContext } from '../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const kibanaServer = getService('kibanaServer'); - const visualTesting = getService('visualTesting'); - const testSubjects = getService('testSubjects'); - const retry = getService('retry'); - const PageObjects = getPageObjects(['common', 'security']); - - describe.skip('Security', () => { - describe('Login Page', () => { - before(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - await PageObjects.security.forceLogout(); - }); - - after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); - }); - - afterEach(async () => { - // NOTE: Logout needs to happen before anything else to avoid flaky behavior - await PageObjects.security.forceLogout(); - }); - - it('renders login page', async () => { - await PageObjects.common.navigateToApp('login'); - - await retry.waitFor( - 'login page visible', - async () => await testSubjects.exists('loginSubmit') - ); - - await visualTesting.snapshot(); - }); - - it('renders failed login', async () => { - await PageObjects.security.loginPage.login('wrong-user', 'wrong-password', { - expectSuccess: false, - }); - - await retry.waitFor( - 'login error visible', - async () => await testSubjects.exists('loginErrorMessage') - ); - - await visualTesting.snapshot(); - }); - }); - }); -} diff --git a/x-pack/test/visual_regression/tests/maps/index.js b/x-pack/test/visual_regression/tests/maps/index.js deleted file mode 100644 index 9d53d70ad2abc4..00000000000000 --- a/x-pack/test/visual_regression/tests/maps/index.js +++ /dev/null @@ -1,61 +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. - */ - -export default function ({ loadTestFile, getService }) { - const kibanaServer = getService('kibanaServer'); - const esArchiver = getService('esArchiver'); - const browser = getService('browser'); - const log = getService('log'); - const supertest = getService('supertest'); - - describe('maps app visual regression', function () { - before(async () => { - await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); - await kibanaServer.importExport.load( - 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' - ); - // Functional tests verify behavior when referenced index pattern saved objects can not be found. - // However, saved object import fails when reference saved objects can not be found. - // To prevent import errors, index pattern saved object references exist during import - // but are then deleted afterwards to enable testing of missing reference index pattern saved objects. - - log.info('Delete index pattern'); - log.debug('id: ' + 'idThatDoesNotExitForESGeoGridSource'); - log.debug('id: ' + 'idThatDoesNotExitForESSearchSource'); - log.debug('id: ' + 'idThatDoesNotExitForESJoinSource'); - await supertest - .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESGeoGridSource') - .set('kbn-xsrf', 'true') - .expect(200); - - await supertest - .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESSearchSource') - .set('kbn-xsrf', 'true') - .expect(200); - - await supertest - .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESJoinSource') - .set('kbn-xsrf', 'true') - .expect(200); - - await esArchiver.load('x-pack/test/functional/es_archives/maps/data'); - await kibanaServer.uiSettings.replace({ - defaultIndex: 'c698b940-e149-11e8-a35a-370a8516603a', - }); - await browser.setWindowSize(1600, 1000); - }); - - after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/maps/data'); - await kibanaServer.importExport.unload( - 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' - ); - }); - - loadTestFile(require.resolve('./vector_styling')); - }); -} diff --git a/x-pack/test/visual_regression/tests/maps/vector_styling.js b/x-pack/test/visual_regression/tests/maps/vector_styling.js deleted file mode 100644 index 092ae603117d9a..00000000000000 --- a/x-pack/test/visual_regression/tests/maps/vector_styling.js +++ /dev/null @@ -1,49 +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. - */ - -export default function ({ getPageObjects, getService }) { - const PageObjects = getPageObjects(['maps']); - const visualTesting = getService('visualTesting'); - - describe('vector styling', () => { - describe('symbolize as icon', () => { - before(async () => { - await PageObjects.maps.loadSavedMap('vector styling icon demo'); - await PageObjects.maps.enterFullScreen(); - await PageObjects.maps.closeLegend(); - }); - - it('should symbolize points as icons with expected color, size, and orientation', async () => { - await visualTesting.snapshot(); - }); - }); - - describe('dynamic coloring', () => { - before(async () => { - await PageObjects.maps.loadSavedMap('join and dynamic coloring demo'); - await PageObjects.maps.enterFullScreen(); - await PageObjects.maps.closeLegend(); - }); - - it('should symbolize fill color with custom steps from join value and border color with dynamic color ramp from prop value', async () => { - await visualTesting.snapshot(); - }); - }); - - describe('dynamic line coloring', () => { - before(async () => { - await PageObjects.maps.loadSavedMap('pew pew demo'); - await PageObjects.maps.enterFullScreen(); - await PageObjects.maps.closeLegend(); - }); - - it('should symbolize pew pew lines', async () => { - await visualTesting.snapshot(); - }); - }); - }); -} diff --git a/yarn.lock b/yarn.lock index 03e4ddaace0931..6d6d6094870e2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4172,90 +4172,6 @@ dependencies: mkdirp "^1.0.4" -"@oclif/color@^0.0.0": - version "0.0.0" - resolved "https://registry.yarnpkg.com/@oclif/color/-/color-0.0.0.tgz#54939bbd16d1387511bf1a48ccda1a417248e6a9" - integrity sha512-KKd3W7eNwfNF061tr663oUNdt8EMnfuyf5Xv55SGWA1a0rjhWqS/32P7OeB7CbXcJUBdfVrPyR//1afaW12AWw== - dependencies: - ansi-styles "^3.2.1" - supports-color "^5.4.0" - tslib "^1" - -"@oclif/command@1.5.19", "@oclif/command@^1.5.13", "@oclif/command@^1.5.3": - version "1.5.19" - resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.5.19.tgz#13f472450eb83bd6c6871a164c03eadb5e1a07ed" - integrity sha512-6+iaCMh/JXJaB2QWikqvGE9//wLEVYYwZd5sud8aLoLKog1Q75naZh2vlGVtg5Mq/NqpqGQvdIjJb3Bm+64AUQ== - dependencies: - "@oclif/config" "^1" - "@oclif/errors" "^1.2.2" - "@oclif/parser" "^3.8.3" - "@oclif/plugin-help" "^2" - debug "^4.1.1" - semver "^5.6.0" - -"@oclif/config@^1": - version "1.13.0" - resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.13.0.tgz#fc2bd82a9cb30a73faf7d2aa5ae937c719492bd1" - integrity sha512-ttb4l85q7SBx+WlUJY4A9eXLgv4i7hGDNGaXnY9fDKrYD7PBMwNOQ3Ssn2YT2yARAjyOxVE/5LfcwhQGq4kzqg== - dependencies: - debug "^4.1.1" - tslib "^1.9.3" - -"@oclif/errors@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.2.2.tgz#9d8f269b15f13d70aa93316fed7bebc24688edc2" - integrity sha512-Eq8BFuJUQcbAPVofDxwdE0bL14inIiwt5EaKRVY9ZDIG11jwdXZqiQEECJx0VfnLyUZdYfRd/znDI/MytdJoKg== - dependencies: - clean-stack "^1.3.0" - fs-extra "^7.0.0" - indent-string "^3.2.0" - strip-ansi "^5.0.0" - wrap-ansi "^4.0.0" - -"@oclif/linewrap@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91" - integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== - -"@oclif/parser@^3.8.3": - version "3.8.4" - resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.8.4.tgz#1a90fc770a42792e574fb896325618aebbe8c9e4" - integrity sha512-cyP1at3l42kQHZtqDS3KfTeyMvxITGwXwH1qk9ktBYvqgMp5h4vHT+cOD74ld3RqJUOZY/+Zi9lb4Tbza3BtuA== - dependencies: - "@oclif/linewrap" "^1.0.0" - chalk "^2.4.2" - tslib "^1.9.3" - -"@oclif/plugin-help@^2": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-2.2.0.tgz#8dfc1c80deae47a205fbc70b018747ba93f31cc3" - integrity sha512-56iIgE7NQfwy/ZrWrvrEfJGb5rrMUt409yoQGw4feiU101UudA1btN1pbUbcKBr7vY9KFeqZZcftXEGxOp7zBg== - dependencies: - "@oclif/command" "^1.5.13" - chalk "^2.4.1" - indent-string "^3.2.0" - lodash.template "^4.4.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - widest-line "^2.0.1" - wrap-ansi "^4.0.0" - -"@oclif/plugin-not-found@^1.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@oclif/plugin-not-found/-/plugin-not-found-1.2.2.tgz#3e601f6e4264d7a0268cd03c152d90aa9c0cec6d" - integrity sha512-SPlmiJFmTFltQT/owdzQwKgq6eq5AEKVwVK31JqbzK48bRWvEL1Ye60cgztXyZ4bpPn2Fl+KeL3FWFQX41qJuA== - dependencies: - "@oclif/color" "^0.0.0" - "@oclif/command" "^1.5.3" - cli-ux "^4.9.0" - fast-levenshtein "^2.0.6" - lodash "^4.17.11" - -"@oclif/screen@^1.0.3": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@oclif/screen/-/screen-1.0.4.tgz#b740f68609dfae8aa71c3a6cab15d816407ba493" - integrity sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw== - "@octokit/app@^2.2.2": version "2.2.2" resolved "https://registry.yarnpkg.com/@octokit/app/-/app-2.2.2.tgz#a1b8248f64159eeccbe4000d888fdae4163c4ad8" @@ -4615,34 +4531,6 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.4.0.tgz#facf2c67d6063b9918d5a5e3fdf25f3a30d547b6" integrity sha512-Hzl8soGpmyzja9w3kiFFcYJ7n5HNETpplY6cb67KR4QPlxp4FTTresO06qXHgHDhyIInmbLJXuwARjjpsKYGuQ== -"@percy/agent@^0.28.6": - version "0.28.6" - resolved "https://registry.yarnpkg.com/@percy/agent/-/agent-0.28.6.tgz#b220fab6ddcf63ae4e6c343108ba6955a772ce1c" - integrity sha512-SDAyBiUmfQMVTayjvEjQ0IJIA7Y3AoeyWn0jmUxNOMRRIJWo4lQJghfhFCgzCkhXDCm67NMN2nAQAsvXrlIdkQ== - dependencies: - "@oclif/command" "1.5.19" - "@oclif/config" "^1" - "@oclif/plugin-help" "^2" - "@oclif/plugin-not-found" "^1.2" - axios "^0.21.1" - body-parser "^1.18.3" - colors "^1.3.2" - cors "^2.8.4" - cosmiconfig "^5.2.1" - cross-spawn "^7.0.2" - deepmerge "^4.0.0" - express "^4.16.3" - follow-redirects "1.12.1" - generic-pool "^3.7.1" - globby "^10.0.1" - image-size "^0.8.2" - js-yaml "^3.13.1" - percy-client "^3.2.0" - puppeteer "^5.3.1" - retry-axios "^1.0.1" - which "^2.0.1" - winston "^3.0.0" - "@pmmmwh/react-refresh-webpack-plugin@^0.5.1": version "0.5.5" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz#e77aac783bd079f548daa0a7f080ab5b5a9741ca" @@ -9240,7 +9128,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -9322,11 +9210,6 @@ agent-base@4: dependencies: es6-promisify "^5.0.0" -agent-base@5: - version "5.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" - integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== - agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -9459,7 +9342,7 @@ ansi-colors@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== -ansi-escapes@^3.0.0, ansi-escapes@^3.1.0: +ansi-escapes@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== @@ -9546,11 +9429,6 @@ ansi-wrap@0.1.0, ansi-wrap@^0.1.0: resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= -ansicolors@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" - integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk= - antlr4ts-cli@^0.5.0-alpha.3: version "0.5.0-alpha.3" resolved "https://registry.yarnpkg.com/antlr4ts-cli/-/antlr4ts-cli-0.5.0-alpha.3.tgz#1f581b2a3c840d3921a2f3b1e739e48c7e7c18cd" @@ -10496,12 +10374,7 @@ blob-util@^2.0.2: resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== -bluebird-retry@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/bluebird-retry/-/bluebird-retry-0.11.0.tgz#1289ab22cbbc3a02587baad35595351dd0c1c047" - integrity sha1-EomrIsu8OgJYe6rTVZU1HdDBwEc= - -bluebird@3.7.2, bluebird@^3.3.5, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.5, bluebird@^3.7.1, bluebird@^3.7.2: +bluebird@3.7.2, bluebird@^3.3.5, bluebird@^3.5.5, bluebird@^3.7.1, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -10511,7 +10384,23 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== -body-parser@1.19.2, body-parser@^1.18.3: +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +body-parser@1.19.2: version "1.19.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw== @@ -10937,6 +10826,11 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -11071,25 +10965,6 @@ call-me-maybe@^1.0.1: resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= -caller-callsite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" - integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= - dependencies: - callsites "^2.0.0" - -caller-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" - integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= - dependencies: - caller-callsite "^2.0.0" - -callsites@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" - integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= - callsites@^3.0.0, callsites@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -11178,14 +11053,6 @@ capture-exit@^2.0.0: dependencies: rsvp "^4.8.4" -cardinal@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505" - integrity sha1-fMEFXYItISlU0HsIXeolHMe8VQU= - dependencies: - ansicolors "~0.3.2" - redeyed "~2.1.0" - case-sensitive-paths-webpack-plugin@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz#23ac613cc9a856e4f88ff8bb73bbb5e989825cf7" @@ -11448,11 +11315,6 @@ clean-css@^4.2.3: dependencies: source-map "~0.6.0" -clean-stack@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31" - integrity sha1-noIVAa6XmYbEax1m0tQy2y/UrjE= - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -11515,33 +11377,6 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-ux@^4.9.0: - version "4.9.3" - resolved "https://registry.yarnpkg.com/cli-ux/-/cli-ux-4.9.3.tgz#4c3e070c1ea23eef010bbdb041192e0661be84ce" - integrity sha512-/1owvF0SZ5Gn54cgrikJ0QskgTzeg30HGjkmjFoaHDJzAqFpuX1DBpFR8aLvsE1J5s9MgeYRENQK4BFwOag5VA== - dependencies: - "@oclif/errors" "^1.2.2" - "@oclif/linewrap" "^1.0.0" - "@oclif/screen" "^1.0.3" - ansi-escapes "^3.1.0" - ansi-styles "^3.2.1" - cardinal "^2.1.1" - chalk "^2.4.1" - clean-stack "^2.0.0" - extract-stack "^1.0.0" - fs-extra "^7.0.0" - hyperlinker "^1.0.0" - indent-string "^3.2.0" - is-wsl "^1.1.0" - lodash "^4.17.11" - password-prompt "^1.0.7" - semver "^5.6.0" - strip-ansi "^5.0.0" - supports-color "^5.5.0" - supports-hyperlinks "^1.0.1" - treeify "^1.1.0" - tslib "^1.9.3" - cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -11756,7 +11591,7 @@ colorette@^2.0.10, colorette@^2.0.14: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== -colors@1.4.0, colors@^1.3.2: +colors@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -11998,6 +11833,13 @@ container-info@^1.0.1: resolved "https://registry.yarnpkg.com/container-info/-/container-info-1.0.1.tgz#6b383cb5e197c8d921e88983388facb04124b56b" integrity sha512-wk/+uJvPHOFG+JSwQS+fw6H6yw3Oyc8Kw9L4O2MN817uA90OqJ59nlZbbLPqDudsjJ7Tetee3pwExdKpd2ahjQ== +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + content-disposition@0.5.4, content-disposition@^0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -12034,6 +11876,11 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + cookie@0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" @@ -12123,24 +11970,6 @@ core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cors@^2.8.4: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -cosmiconfig@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" - integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== - dependencies: - import-fresh "^2.0.0" - is-directory "^0.3.1" - js-yaml "^3.13.1" - parse-json "^4.0.0" - cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -12260,7 +12089,7 @@ cross-env@^6.0.3: dependencies: cross-spawn "^7.0.0" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -13256,7 +13085,7 @@ deep-object-diff@^1.1.0: resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.0.tgz#d6fabf476c2ed1751fc94d5ca693d2ed8c18bc5a" integrity sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw== -deepmerge@3.2.0, deepmerge@^2.1.1, deepmerge@^4.0.0, deepmerge@^4.2.2: +deepmerge@3.2.0, deepmerge@^2.1.1, deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== @@ -13491,11 +13320,6 @@ detective@^5.0.2, detective@^5.2.0: defined "^1.0.0" minimist "^1.1.1" -devtools-protocol@0.0.818844: - version "0.0.818844" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.818844.tgz#d1947278ec85b53e4c8ca598f607a28fa785ba9e" - integrity sha512-AD1hi7iVJ8OD0aMLQU5VK0XH9LDlA1+BcPIgrAxPfaibx2DbWucuyOhc4oyQCbnvDDO68nN6/LcKfqTP343Jjg== - devtools-protocol@0.0.901419: version "0.0.901419" resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.901419.tgz#79b5459c48fe7e1c5563c02bd72f8fec3e0cebcd" @@ -13755,7 +13579,7 @@ dotenv@^16.0.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d" integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== -dotenv@^8.0.0, dotenv@^8.1.0: +dotenv@^8.0.0: version "8.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== @@ -14269,11 +14093,6 @@ es6-map@^0.1.5: es6-symbol "~3.1.1" event-emitter "~0.3.5" -es6-promise-pool@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/es6-promise-pool/-/es6-promise-pool-2.5.0.tgz#147c612b36b47f105027f9d2bf54a598a99d9ccb" - integrity sha1-FHxhKza0fxBQJ/nSv1SlmKmdnMs= - es6-promise@^4.0.3, es6-promise@^4.2.8: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" @@ -14677,7 +14496,7 @@ espree@^7.3.0, espree@^7.3.1: acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" -esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -14927,7 +14746,43 @@ expose-loader@^0.7.5: resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-0.7.5.tgz#e29ea2d9aeeed3254a3faa1b35f502db9f9c3f6f" integrity sha512-iPowgKUZkTPX5PznYsmifVj9Bob0w2wTHVkt/eYNPSzyebkUgIedmskf/kcfEIWpiWjg3JRjnW+a17XypySMuw== -express@^4.16.3, express@^4.17.1, express@^4.17.3: +express@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +express@^4.17.3: version "4.17.3" resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== @@ -15006,12 +14861,7 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-stack@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/extract-stack/-/extract-stack-1.0.0.tgz#b97acaf9441eea2332529624b732fc5a1c8165fa" - integrity sha1-uXrK+UQe6iMyUpYktzL8WhyBZfo= - -extract-zip@2.0.1, extract-zip@^2.0.0, extract-zip@^2.0.1: +extract-zip@2.0.1, extract-zip@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== @@ -15425,11 +15275,6 @@ folktale@2.3.2: resolved "https://registry.yarnpkg.com/folktale/-/folktale-2.3.2.tgz#38231b039e5ef36989920cbf805bf6b227bf4fd4" integrity sha512-+8GbtQBwEqutP0v3uajDDoN64K2ehmHd0cjlghhxh0WpcfPzAIjPA03e1VvHlxL02FVGR0A6lwXsNQKn3H1RNQ== -follow-redirects@1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6" - integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg== - follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.9: version "1.15.0" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.0.tgz#06441868281c86d0dda4ad8bdaead2d02dca89d4" @@ -15457,11 +15302,6 @@ foreach@^2.0.5: resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= -foreachasync@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/foreachasync/-/foreachasync-3.0.0.tgz#5502987dc8714be3392097f32e0071c9dee07cf6" - integrity sha1-VQKYfchxS+M5IJfzLgBxyd7gfPY= - foreground-child@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" @@ -15627,7 +15467,7 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^7.0.0, fs-extra@^7.0.1: +fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -15783,12 +15623,12 @@ geckodriver@^3.0.2: https-proxy-agent "5.0.0" tar "6.1.11" -generic-pool@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.7.1.tgz#36fe5bb83e7e0e032e5d32cd05dc00f5ff119aa8" - integrity sha512-ug6DAZoNgWm6q5KhPFA+hzXfBLFQu5sTXxPpv44DmE0A2g+CiHoq9LTVdkXpZMkYVMoGw83F6W+WT0h0MFMK/w== +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== -gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: +gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -16394,11 +16234,6 @@ has-bigints@^1.0.1: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -16851,6 +16686,17 @@ http-deceiver@^1.2.7: resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= +http-errors@1.7.2, http-errors@~1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + http-errors@1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" @@ -16965,14 +16811,6 @@ https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: agent-base "6" debug "4" -https-proxy-agent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" - integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg== - dependencies: - agent-base "5" - debug "4" - human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -16990,11 +16828,6 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -hyperlinker@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" - integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== - hyphenate-style-name@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" @@ -17063,13 +16896,6 @@ ignore@^5.0.5, ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== -image-size@^0.8.2: - version "0.8.3" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.8.3.tgz#f0b568857e034f29baffd37013587f2c0cad8b46" - integrity sha512-SMtq1AJ+aqHB45c3FsB4ERK0UCiA2d3H1uq8s+8T0Pf8A3W4teyBQyaFaktH6xvZqh+npwlKU7i4fJo0r7TYTg== - dependencies: - queue "6.0.1" - immediate@~3.0.5: version "3.0.6" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" @@ -17080,14 +16906,6 @@ immer@^9.0.15, immer@^9.0.7: resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc" integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ== -import-fresh@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" - integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= - dependencies: - caller-path "^2.0.0" - resolve-from "^3.0.0" - import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" @@ -17119,7 +16937,7 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indent-string@^3.0.0, indent-string@^3.2.0: +indent-string@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= @@ -17515,11 +17333,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-directory@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" - integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= - is-docker@^2.0.0, is-docker@^2.1.1: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" @@ -18968,11 +18781,6 @@ jsprim@^2.0.2: json-schema "0.4.0" verror "1.10.0" -jssha@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/jssha/-/jssha-2.3.1.tgz#147b2125369035ca4b2f7d210dc539f009b3de9a" - integrity sha1-FHshJTaQNcpLL30hDcU58Amz3po= - jsts@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/jsts/-/jsts-1.6.2.tgz#c0efc885edae06ae84f78cbf2a0110ba929c5925" @@ -19411,11 +19219,6 @@ lodash-es@^4.17.21: resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -19541,21 +19344,6 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.template@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.toarray@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" @@ -21178,7 +20966,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@4.X, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@4.X, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -21858,14 +21646,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -password-prompt@^1.0.7: - version "1.1.2" - resolved "https://registry.yarnpkg.com/password-prompt/-/password-prompt-1.1.2.tgz#85b2f93896c5bd9e9f2d6ff0627fa5af3dc00923" - integrity sha512-bpuBhROdrhuN3E7G/koAju0WjVw9/uQOG5Co5mokNj0MiOSBVZS1JTwM4zl55hu0WFmIEFvO9cU9sJQiBIYeIA== - dependencies: - ansi-escapes "^3.1.0" - cross-spawn "^6.0.5" - path-browserify@0.0.1, path-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" @@ -21996,21 +21776,6 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -percy-client@^3.2.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/percy-client/-/percy-client-3.7.0.tgz#780e7d780c7f646e59ffb6ee9d3d16e8237851ff" - integrity sha512-5levWR/nfVuSDL9YPN9Sn1M41I2/FmC/FndhD84s6W+mrVC4mB0cc9cT9F58hLuh7/133I/YvyI9Vc6NN41+2g== - dependencies: - bluebird "^3.5.1" - bluebird-retry "^0.11.0" - dotenv "^8.1.0" - es6-promise-pool "^2.5.0" - jssha "^2.1.0" - regenerator-runtime "^0.13.1" - request "^2.87.0" - request-promise "^4.2.2" - walk "^2.3.14" - performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" @@ -22758,7 +22523,7 @@ progress@^1.1.8: resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= -progress@^2.0.0, progress@^2.0.1, progress@^2.0.3: +progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -22902,7 +22667,7 @@ protocol-buffers-schema@^3.3.1: resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz#00434f608b4e8df54c59e070efeefc37fb4bb859" integrity sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w== -proxy-addr@~2.0.7: +proxy-addr@~2.0.5, proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -22915,7 +22680,7 @@ proxy-from-env@1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= -proxy-from-env@1.1.0, proxy-from-env@^1.0.0, proxy-from-env@^1.1.0: +proxy-from-env@1.1.0, proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== @@ -23030,29 +22795,16 @@ puppeteer@^10.2.0: unbzip2-stream "1.3.3" ws "7.4.6" -puppeteer@^5.3.1: - version "5.5.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.5.0.tgz#331a7edd212ca06b4a556156435f58cbae08af00" - integrity sha512-OM8ZvTXAhfgFA7wBIIGlPQzvyEETzDjeRa4mZRCRHxYL+GNH5WAuYUQdja3rpWZvkX/JKqmuVgbsxDNsDFjMEg== - dependencies: - debug "^4.1.0" - devtools-protocol "0.0.818844" - extract-zip "^2.0.0" - https-proxy-agent "^4.0.0" - node-fetch "^2.6.1" - pkg-dir "^4.2.0" - progress "^2.0.1" - proxy-from-env "^1.0.0" - rimraf "^3.0.2" - tar-fs "^2.0.0" - unbzip2-stream "^1.3.3" - ws "^7.2.3" - q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + qs@6.9.7: version "6.9.7" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" @@ -23094,13 +22846,6 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== -queue@6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.1.tgz#abd5a5b0376912f070a25729e0b6a7d565683791" - integrity sha512-AJBQabRCCNr9ANq8v77RJEv73DPbn55cdTb+Giq4X0AVnNVZvMHlYp7XlQiN+1npCZj1DuSmaA2hYVUUDgxFDg== - dependencies: - inherits "~2.0.3" - quick-format-unescaped@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz#6d6b66b8207aa2b35eef12be1421bb24c428f652" @@ -23190,6 +22935,16 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + raw-body@2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" @@ -24035,13 +23790,6 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -redeyed@~2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/redeyed/-/redeyed-2.1.1.tgz#8984b5815d99cb220469c99eeeffe38913e6cc0b" - integrity sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs= - dependencies: - esprima "~4.0.0" - reduce-reducers@*, reduce-reducers@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reduce-reducers/-/reduce-reducers-1.0.4.tgz#fb77e751a9eb0201760ac5a605ca8c9c2d0537f8" @@ -24148,10 +23896,10 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.13.1, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.15.0: version "0.15.0" @@ -24457,13 +24205,6 @@ request-progress@^3.0.0: dependencies: throttleit "^1.0.0" -request-promise-core@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" - integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== - dependencies: - lodash "^4.17.11" - request-promise-core@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" @@ -24480,17 +24221,7 @@ request-promise-native@^1.0.8: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request-promise@^4.2.2: - version "4.2.4" - resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.4.tgz#1c5ed0d71441e38ad58c7ce4ea4ea5b06d54b310" - integrity sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg== - dependencies: - bluebird "^3.5.0" - request-promise-core "1.1.2" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.44.0, request@^2.87.0, request@^2.88.0, request@^2.88.2: +request@^2.44.0, request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -24572,11 +24303,6 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -24683,11 +24409,6 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -retry-axios@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/retry-axios/-/retry-axios-1.0.1.tgz#c1e465126416d8aee7a0a2d4be28401cc0135029" - integrity sha512-aVnENElFbdmbsv1WbTi610Ukdper88yUPz4Y3eg/DUyHV7vNaLrj9orB6FOjvmFoXL9wZvbMAsOD87BmcyBVOw== - retry@0.12.0, retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -25103,6 +24824,25 @@ semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semve dependencies: lru-cache "^6.0.0" +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + send@0.17.2: version "0.17.2" resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" @@ -25167,6 +24907,16 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + serve-static@1.14.2: version "1.14.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" @@ -25227,6 +24977,11 @@ setprototypeof@1.1.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" @@ -26429,7 +26184,7 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -26443,15 +26198,15 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-hyperlinks@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" - integrity sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw== +supports-hyperlinks@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" + integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA== dependencies: - has-flag "^2.0.0" - supports-color "^5.0.0" + has-flag "^4.0.0" + supports-color "^7.0.0" -supports-hyperlinks@^2.0.0, supports-hyperlinks@^2.2.0: +supports-hyperlinks@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== @@ -26991,6 +26746,11 @@ toggle-selection@^1.0.6: resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -27193,7 +26953,7 @@ tslib@2.3.1: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@^1, tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.13.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== @@ -27281,7 +27041,7 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.18: +type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -27373,14 +27133,6 @@ unbzip2-stream@1.3.3: buffer "^5.2.1" through "^2.3.8" -unbzip2-stream@^1.3.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" - integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -28000,7 +27752,7 @@ variable-diff@1.1.0: chalk "^1.1.1" object-assign "^4.0.1" -vary@^1, vary@~1.1.2: +vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= @@ -28473,13 +28225,6 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -walk@^2.3.14: - version "2.3.14" - resolved "https://registry.yarnpkg.com/walk/-/walk-2.3.14.tgz#60ec8631cfd23276ae1e7363ce11d626452e1ef3" - integrity sha512-5skcWAUmySj6hkBdH6B6+3ddMjVQYH5Qy9QGbPmN8kVmLteXk+yVXg+yfk1nbX30EYakahLrr8iPcCxJQSCBeg== - dependencies: - foreachasync "^3.0.0" - walker@^1.0.7, walker@~1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" @@ -28889,13 +28634,6 @@ wide-align@^1.1.2, wide-align@^1.1.5: dependencies: string-width "^1.0.2 || 2 || 3 || 4" -widest-line@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== - dependencies: - string-width "^2.1.1" - widest-line@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" @@ -28920,7 +28658,7 @@ windows-release@^3.1.0: dependencies: execa "^1.0.0" -winston-transport@^4.5.0: +winston-transport@^4.4.2, winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== @@ -28929,7 +28667,23 @@ winston-transport@^4.5.0: readable-stream "^3.6.0" triple-beam "^1.3.0" -winston@^3.0.0, winston@^3.3.3, winston@^3.8.1: +winston@^3.3.3: + version "3.5.1" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.5.1.tgz#b25cc899d015836dbf8c583dec8c4c4483a0da2e" + integrity sha512-tbRtVy+vsSSCLcZq/8nXZaOie/S2tPXPFt4be/Q3vI/WtYwm7rrwidxVw2GRa38FIXcJ1kUM6MOZ9Jmnk3F3UA== + dependencies: + "@dabh/diagnostics" "^2.0.2" + async "^3.2.3" + is-stream "^2.0.0" + logform "^2.3.2" + one-time "^1.0.0" + readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.4.2" + +winston@^3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/winston/-/winston-3.8.1.tgz#76f15b3478cde170b780234e0c4cf805c5a7fb57" integrity sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w== @@ -28995,15 +28749,6 @@ wrap-ansi@^3.0.1: string-width "^2.1.1" strip-ansi "^4.0.0" -wrap-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-4.0.0.tgz#b3570d7c70156159a2d42be5cc942e957f7b1131" - integrity sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg== - dependencies: - ansi-styles "^3.2.0" - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" From 18111b3e222e80306748786848a0b2ca759ae487 Mon Sep 17 00:00:00 2001 From: Spencer <spencer@elastic.co> Date: Mon, 12 Sep 2022 16:01:51 -0500 Subject: [PATCH 087/144] [kbn/pm] add hidden script for migration purposes (#140554) --- kbn_pm/src/cli.mjs | 4 ++-- .../src/commands/bootstrap/bootstrap_command.mjs | 8 +++----- .../bootstrap/regenerate_base_tsconfig.mjs | 8 ++++---- .../regenerate_synthetic_package_map.mjs | 6 +++--- kbn_pm/src/commands/bootstrap/yarn.mjs | 6 +++--- kbn_pm/src/commands/index.mjs | 8 ++++++++ kbn_pm/src/commands/test_command.mjs | 15 +++++++++++++++ kbn_pm/src/lib/find_clean_paths.mjs | 2 +- kbn_pm/src/lib/help.mjs | 6 +++--- 9 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 kbn_pm/src/commands/test_command.mjs diff --git a/kbn_pm/src/cli.mjs b/kbn_pm/src/cli.mjs index 99d8262f92aa9b..2c9d1019b588f5 100644 --- a/kbn_pm/src/cli.mjs +++ b/kbn_pm/src/cli.mjs @@ -18,7 +18,7 @@ import { Args } from './lib/args.mjs'; import { getHelp } from './lib/help.mjs'; import { createFlagError, isCliError } from './lib/cli_error.mjs'; -import { COMMANDS } from './commands/index.mjs'; +import { getCmd } from './commands/index.mjs'; import { Log } from './lib/log.mjs'; const start = Date.now(); @@ -39,7 +39,7 @@ async function tryToGetCiStatsReporter(log) { } try { - const cmd = cmdName ? COMMANDS.find((c) => c.name === cmdName) : undefined; + const cmd = getCmd(cmdName); if (cmdName && !cmd) { throw createFlagError(`Invalid command name [${cmdName}]`); diff --git a/kbn_pm/src/commands/bootstrap/bootstrap_command.mjs b/kbn_pm/src/commands/bootstrap/bootstrap_command.mjs index 328971313039ac..5a2575c6454151 100644 --- a/kbn_pm/src/commands/bootstrap/bootstrap_command.mjs +++ b/kbn_pm/src/commands/bootstrap/bootstrap_command.mjs @@ -76,7 +76,7 @@ export const command = { // That is only intended during the migration process while non Bazel projects are not removed at all. if (forceInstall) { await time('force install dependencies', async () => { - removeYarnIntegrityFileIfExists(); + await removeYarnIntegrityFileIfExists(); await Bazel.expungeCache(log, { quiet }); await Bazel.installYarnDeps(log, { offline, quiet }); }); @@ -89,19 +89,17 @@ export const command = { // generate the synthetic package map which powers several other features, needed // as an input to the package build await time('regenerate synthetic package map', async () => { - regenerateSyntheticPackageMap(plugins); + await regenerateSyntheticPackageMap(plugins); }); - // build packages await time('build packages', async () => { await Bazel.buildPackages(log, { offline, quiet }); }); - await time('sort package json', async () => { await sortPackageJson(); }); await time('regenerate tsconfig.base.json', async () => { - regenerateBaseTsconfig(plugins); + await regenerateBaseTsconfig(plugins); }); if (validate) { diff --git a/kbn_pm/src/commands/bootstrap/regenerate_base_tsconfig.mjs b/kbn_pm/src/commands/bootstrap/regenerate_base_tsconfig.mjs index 69b288f7981bb4..3cf71531614a57 100644 --- a/kbn_pm/src/commands/bootstrap/regenerate_base_tsconfig.mjs +++ b/kbn_pm/src/commands/bootstrap/regenerate_base_tsconfig.mjs @@ -7,7 +7,7 @@ */ import Path from 'path'; -import Fs from 'fs'; +import Fsp from 'fs/promises'; import { REPO_ROOT } from '../../lib/paths.mjs'; import { convertPluginIdToPackageId } from './plugins.mjs'; @@ -16,9 +16,9 @@ import { normalizePath } from './normalize_path.mjs'; /** * @param {import('@kbn/plugin-discovery').KibanaPlatformPlugin[]} plugins */ -export function regenerateBaseTsconfig(plugins) { +export async function regenerateBaseTsconfig(plugins) { const tsconfigPath = Path.resolve(REPO_ROOT, 'tsconfig.base.json'); - const lines = Fs.readFileSync(tsconfigPath, 'utf-8').split('\n'); + const lines = (await Fsp.readFile(tsconfigPath, 'utf-8')).split('\n'); const packageMap = plugins .slice() @@ -32,7 +32,7 @@ export function regenerateBaseTsconfig(plugins) { const start = lines.findIndex((l) => l.trim() === '// START AUTOMATED PACKAGE LISTING'); const end = lines.findIndex((l) => l.trim() === '// END AUTOMATED PACKAGE LISTING'); - Fs.writeFileSync( + await Fsp.writeFile( tsconfigPath, [...lines.slice(0, start + 1), ...packageMap, ...lines.slice(end)].join('\n') ); diff --git a/kbn_pm/src/commands/bootstrap/regenerate_synthetic_package_map.mjs b/kbn_pm/src/commands/bootstrap/regenerate_synthetic_package_map.mjs index 22898daa92b211..ea1f53727997d5 100644 --- a/kbn_pm/src/commands/bootstrap/regenerate_synthetic_package_map.mjs +++ b/kbn_pm/src/commands/bootstrap/regenerate_synthetic_package_map.mjs @@ -7,7 +7,7 @@ */ import Path from 'path'; -import Fs from 'fs'; +import Fsp from 'fs/promises'; import { normalizePath } from './normalize_path.mjs'; import { REPO_ROOT } from '../../lib/paths.mjs'; @@ -16,7 +16,7 @@ import { convertPluginIdToPackageId } from './plugins.mjs'; /** * @param {import('@kbn/plugin-discovery').KibanaPlatformPlugin[]} plugins */ -export function regenerateSyntheticPackageMap(plugins) { +export async function regenerateSyntheticPackageMap(plugins) { /** @type {Array<[string, string]>} */ const entries = [['@kbn/core', 'src/core']]; @@ -27,7 +27,7 @@ export function regenerateSyntheticPackageMap(plugins) { ]); } - Fs.writeFileSync( + await Fsp.writeFile( Path.resolve(REPO_ROOT, 'packages/kbn-synthetic-package-map/synthetic-packages.json'), JSON.stringify(entries, null, 2) ); diff --git a/kbn_pm/src/commands/bootstrap/yarn.mjs b/kbn_pm/src/commands/bootstrap/yarn.mjs index db11c3b12930e6..652c5cdb38b6e5 100644 --- a/kbn_pm/src/commands/bootstrap/yarn.mjs +++ b/kbn_pm/src/commands/bootstrap/yarn.mjs @@ -7,20 +7,20 @@ */ import Path from 'path'; -import Fs from 'fs'; +import Fsp from 'fs/promises'; import { REPO_ROOT } from '../../lib/paths.mjs'; import { maybeRealpath, isFile, isDirectory } from '../../lib/fs.mjs'; // yarn integrity file checker -export function removeYarnIntegrityFileIfExists() { +export async function removeYarnIntegrityFileIfExists() { try { const nodeModulesRealPath = maybeRealpath(Path.resolve(REPO_ROOT, 'node_modules')); const yarnIntegrityFilePath = Path.resolve(nodeModulesRealPath, '.yarn-integrity'); // check if the file exists and delete it in that case if (isFile(yarnIntegrityFilePath)) { - Fs.unlinkSync(yarnIntegrityFilePath); + await Fsp.unlink(yarnIntegrityFilePath); } } catch { // no-op diff --git a/kbn_pm/src/commands/index.mjs b/kbn_pm/src/commands/index.mjs index 8d4638310d3290..f8b63d7afe5fce 100644 --- a/kbn_pm/src/commands/index.mjs +++ b/kbn_pm/src/commands/index.mjs @@ -12,4 +12,12 @@ export const COMMANDS = [ (await import('./run_in_packages_command.mjs')).command, (await import('./clean_command.mjs')).command, (await import('./reset_command.mjs')).command, + (await import('./test_command.mjs')).command, ]; + +/** + * @param {string | undefined} name + */ +export function getCmd(name) { + return COMMANDS.find((c) => (c.name.startsWith('_') ? c.name.slice(1) : c.name) === name); +} diff --git a/kbn_pm/src/commands/test_command.mjs b/kbn_pm/src/commands/test_command.mjs new file mode 100644 index 00000000000000..e425c5b94698d7 --- /dev/null +++ b/kbn_pm/src/commands/test_command.mjs @@ -0,0 +1,15 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** @type {import('../lib/command').Command} */ +export const command = { + name: '_test', + async run({ log }) { + log.success('empty'); + }, +}; diff --git a/kbn_pm/src/lib/find_clean_paths.mjs b/kbn_pm/src/lib/find_clean_paths.mjs index e98a949971487f..a15118031038b5 100644 --- a/kbn_pm/src/lib/find_clean_paths.mjs +++ b/kbn_pm/src/lib/find_clean_paths.mjs @@ -30,7 +30,7 @@ async function tryToGetSyntheticPackageMap(log) { } /** - * @param {*} packageDir + * @param {string} packageDir * @returns {string[]} */ export function readCleanPatterns(packageDir) { diff --git a/kbn_pm/src/lib/help.mjs b/kbn_pm/src/lib/help.mjs index bce93df47e9411..28f61bb65c56f5 100644 --- a/kbn_pm/src/lib/help.mjs +++ b/kbn_pm/src/lib/help.mjs @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { COMMANDS } from '../commands/index.mjs'; +import { COMMANDS, getCmd } from '../commands/index.mjs'; import { dedent, indent } from './indent.mjs'; import { title } from './colors.mjs'; @@ -15,7 +15,7 @@ import { title } from './colors.mjs'; * @returns {Promise<string>} */ export async function getHelp(cmdName = undefined) { - const cmd = cmdName && COMMANDS.find((c) => c.name === cmdName); + const cmd = getCmd(cmdName); /** * @param {number} depth @@ -49,6 +49,6 @@ export async function getHelp(cmdName = undefined) { ' yarn kbn <command> [...flags]', '', 'Commands:', - ...COMMANDS.map((cmd) => cmdLines(2, cmd)).flat(), + ...COMMANDS.flatMap((cmd) => (cmd.name.startsWith('_') ? [] : cmdLines(2, cmd))), ].join('\n'); } From 4f346c381640ed2d134b017c9b3511782f9cc61a Mon Sep 17 00:00:00 2001 From: Steph Milovic <stephanie.milovic@elastic.co> Date: Mon, 12 Sep 2022 16:06:48 -0600 Subject: [PATCH 088/144] do not dispatch action if socTrends is not enabled (#140327) --- .../use_init_timerange_url_params.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_timerange_url_params.ts b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_timerange_url_params.ts index 673ca827c53021..824733a4f18fdb 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_timerange_url_params.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/search_bar/use_init_timerange_url_params.ts @@ -60,20 +60,14 @@ const initializeTimerangeFromUrlParam = ( if (isEmpty(globalLinkTo.linkTo)) { dispatch(inputsActions.removeLinkTo([InputsModelId.global, InputsModelId.timeline])); - dispatch( - inputsActions.removeLinkTo([ - InputsModelId.global, - ...(isSocTrendsEnabled ? [InputsModelId.socTrends] : []), - ]) - ); + if (isSocTrendsEnabled) { + dispatch(inputsActions.removeLinkTo([InputsModelId.global, InputsModelId.socTrends])); + } } else { dispatch(inputsActions.addLinkTo([InputsModelId.global, InputsModelId.timeline])); - dispatch( - inputsActions.addLinkTo([ - InputsModelId.global, - ...(isSocTrendsEnabled ? [InputsModelId.socTrends] : []), - ]) - ); + if (isSocTrendsEnabled) { + dispatch(inputsActions.addLinkTo([InputsModelId.global, InputsModelId.socTrends])); + } } if (isEmpty(timelineLinkTo.linkTo)) { From 49d49b67a158842beb2d1d3cb7cf73a3fc8e16e4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Sep 2022 17:43:09 -0500 Subject: [PATCH 089/144] Update babel to ^7.19.0 (main) (#140556) * Update babel to ^7.19.0 * dedupe * dedupe 2 * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jonathan Budzenski <jon@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 16 +- yarn.lock | 418 ++++++++++++++++----------------------------------- 2 files changed, 136 insertions(+), 298 deletions(-) diff --git a/package.json b/package.json index 41e22f2320ba7a..9947161017b8af 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ }, "dependencies": { "@appland/sql-parser": "^1.5.1", - "@babel/runtime": "^7.18.9", + "@babel/runtime": "^7.19.0", "@dnd-kit/core": "^3.1.1", "@dnd-kit/sortable": "^4.0.0", "@dnd-kit/utilities": "^2.0.0", @@ -629,12 +629,12 @@ "devDependencies": { "@apidevtools/swagger-parser": "^10.0.3", "@babel/cli": "^7.18.10", - "@babel/core": "^7.18.13", + "@babel/core": "^7.19.0", "@babel/eslint-parser": "^7.18.9", "@babel/eslint-plugin": "^7.18.10", - "@babel/generator": "^7.18.13", - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/parser": "^7.18.13", + "@babel/generator": "^7.19.0", + "@babel/helper-plugin-utils": "^7.19.0", + "@babel/parser": "^7.19.0", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/plugin-proposal-export-namespace-from": "^7.18.9", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", @@ -642,12 +642,12 @@ "@babel/plugin-proposal-optional-chaining": "^7.18.9", "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-transform-runtime": "^7.18.10", - "@babel/preset-env": "^7.18.10", + "@babel/preset-env": "^7.19.0", "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.18.6", "@babel/register": "^7.18.9", - "@babel/traverse": "^7.18.13", - "@babel/types": "^7.18.13", + "@babel/traverse": "^7.19.0", + "@babel/types": "^7.19.0", "@bazel/ibazel": "^0.16.2", "@bazel/typescript": "4.6.2", "@cypress/code-coverage": "^3.9.12", diff --git a/yarn.lock b/yarn.lock index 6d6d6094870e2e..1a56456289f138 100644 --- a/yarn.lock +++ b/yarn.lock @@ -81,10 +81,10 @@ dependencies: "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8": - version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" - integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.0.tgz#2a592fd89bacb1fcde68de31bee4f2f2dacb0e86" + integrity sha512-y5rqgTTPTmaF5e2nVhOxw+Ur9HDJLsWb6U/KpgUzRZEdPfE6VOubXBKLdbcUTijzRptednSBDQbYZBOSqJxpJw== "@babel/core@7.12.9": version "7.12.9" @@ -108,21 +108,21 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.18.13", "@babel/core@^7.7.5": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.13.tgz#9be8c44512751b05094a4d3ab05fc53a47ce00ac" - integrity sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A== +"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.19.0", "@babel/core@^7.7.5": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.0.tgz#d2f5f4f2033c00de8096be3c9f45772563e150c3" + integrity sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ== dependencies: "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.18.13" - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-module-transforms" "^7.18.9" - "@babel/helpers" "^7.18.9" - "@babel/parser" "^7.18.13" + "@babel/generator" "^7.19.0" + "@babel/helper-compilation-targets" "^7.19.0" + "@babel/helper-module-transforms" "^7.19.0" + "@babel/helpers" "^7.19.0" + "@babel/parser" "^7.19.0" "@babel/template" "^7.18.10" - "@babel/traverse" "^7.18.13" - "@babel/types" "^7.18.13" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -145,12 +145,12 @@ dependencies: eslint-rule-composer "^0.3.0" -"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.18.13": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.13.tgz#59550cbb9ae79b8def15587bdfbaa388c4abf212" - integrity sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ== +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" + integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== dependencies: - "@babel/types" "^7.18.13" + "@babel/types" "^7.19.0" "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" @@ -169,12 +169,12 @@ "@babel/helper-explode-assignable-expression" "^7.18.6" "@babel/types" "^7.18.9" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" - integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.0.tgz#537ec8339d53e806ed422f1e06c8f17d55b96bb0" + integrity sha512-Ai5bNWXIvwDvWM7njqsG3feMlL9hCVQsPYXodsZyLwshYkZVJt59Gftau4VrE8S9IT9asd2uSP1hG6wCNw+sXA== dependencies: - "@babel/compat-data" "^7.18.8" + "@babel/compat-data" "^7.19.0" "@babel/helper-validator-option" "^7.18.6" browserslist "^4.20.2" semver "^6.3.0" @@ -192,10 +192,10 @@ "@babel/helper-replace-supers" "^7.18.9" "@babel/helper-split-export-declaration" "^7.18.6" -"@babel/helper-create-regexp-features-plugin@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz#3e35f4e04acbbf25f1b3534a657610a000543d3c" - integrity sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" regexpu-core "^5.1.0" @@ -238,13 +238,13 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-function-name@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0" - integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A== +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== dependencies: - "@babel/template" "^7.18.6" - "@babel/types" "^7.18.9" + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" @@ -267,19 +267,19 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712" - integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" + integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" "@babel/helper-simple-access" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.18.6" - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" @@ -293,10 +293,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f" - integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" + integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" @@ -365,14 +365,14 @@ "@babel/traverse" "^7.18.9" "@babel/types" "^7.18.9" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9" - integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18" + integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg== dependencies: - "@babel/template" "^7.18.6" - "@babel/traverse" "^7.18.9" - "@babel/types" "^7.18.9" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" "@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": version "7.18.6" @@ -383,10 +383,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.3", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.13": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.13.tgz#5b2dd21cae4a2c5145f1fbd8ca103f9313d3b7e4" - integrity sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg== +"@babel/parser@^7.1.0", "@babel/parser@^7.10.3", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.0.tgz#497fcafb1d5b61376959c1c338745ef0577aa02c" + integrity sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -404,13 +404,13 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" "@babel/plugin-proposal-optional-chaining" "^7.18.9" -"@babel/plugin-proposal-async-generator-functions@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz#85ea478c98b0095c3e4102bff3b67d306ed24952" - integrity sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew== +"@babel/plugin-proposal-async-generator-functions@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.0.tgz#cf5740194f170467df20581712400487efc79ff1" + integrity sha512-nhEByMUTx3uZueJ/QkJuSlCfN4FGg+xy+vRsfGQGzSauq5ks2Deid2+05Q3KhfaUjvec1IGhw/Zm3cFm8JigTQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" @@ -750,16 +750,17 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz#90818efc5b9746879b869d5ce83eb2aa48bbc3da" - integrity sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g== +"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" + integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.19.0" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-replace-supers" "^7.18.9" "@babel/helper-split-export-declaration" "^7.18.6" globals "^11.1.0" @@ -771,10 +772,10 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz#68906549c021cb231bee1db21d3b5b095f8ee292" - integrity sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA== +"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.18.13": + version "7.18.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5" + integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -858,14 +859,14 @@ "@babel/helper-simple-access" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz#545df284a7ac6a05125e3e405e536c5853099a06" - integrity sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A== +"@babel/plugin-transform-modules-systemjs@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f" + integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A== dependencies: "@babel/helper-hoist-variables" "^7.18.6" - "@babel/helper-module-transforms" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-module-transforms" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-validator-identifier" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" @@ -877,13 +878,13 @@ "@babel/helper-module-transforms" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-named-capturing-groups-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz#c89bfbc7cc6805d692f3a49bc5fc1b630007246d" - integrity sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.0.tgz#58c52422e4f91a381727faed7d513c89d7f41ada" + integrity sha512-HDSuqOQzkU//kfGdiHBt71/hkDTApw4U/cMVgKgX7PqfB3LOaK+2GtCEsBu1dL9CkswDm0Gwehht1dCr421ULQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.18.6" - "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-create-regexp-features-plugin" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/plugin-transform-new-target@^7.18.6": version "7.18.6" @@ -981,12 +982,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz#6ea7a6297740f381c540ac56caf75b05b74fb664" - integrity sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA== +"@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== dependencies: - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" "@babel/plugin-transform-sticky-regex@^7.18.6": @@ -1034,18 +1035,18 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.16.0", "@babel/preset-env@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.10.tgz#83b8dfe70d7eea1aae5a10635ab0a5fe60dfc0f4" - integrity sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA== +"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.16.0", "@babel/preset-env@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.0.tgz#fd18caf499a67d6411b9ded68dc70d01ed1e5da7" + integrity sha512-1YUju1TAFuzjIQqNM9WsF4U6VbD/8t3wEAlw3LFYuuEr+ywqLRcSXxFKz4DCEj+sN94l/XTDiUXYRrsvMpz9WQ== dependencies: - "@babel/compat-data" "^7.18.8" - "@babel/helper-compilation-targets" "^7.18.9" - "@babel/helper-plugin-utils" "^7.18.9" + "@babel/compat-data" "^7.19.0" + "@babel/helper-compilation-targets" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/helper-validator-option" "^7.18.6" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" - "@babel/plugin-proposal-async-generator-functions" "^7.18.10" + "@babel/plugin-proposal-async-generator-functions" "^7.19.0" "@babel/plugin-proposal-class-properties" "^7.18.6" "@babel/plugin-proposal-class-static-block" "^7.18.6" "@babel/plugin-proposal-dynamic-import" "^7.18.6" @@ -1079,9 +1080,9 @@ "@babel/plugin-transform-async-to-generator" "^7.18.6" "@babel/plugin-transform-block-scoped-functions" "^7.18.6" "@babel/plugin-transform-block-scoping" "^7.18.9" - "@babel/plugin-transform-classes" "^7.18.9" + "@babel/plugin-transform-classes" "^7.19.0" "@babel/plugin-transform-computed-properties" "^7.18.9" - "@babel/plugin-transform-destructuring" "^7.18.9" + "@babel/plugin-transform-destructuring" "^7.18.13" "@babel/plugin-transform-dotall-regex" "^7.18.6" "@babel/plugin-transform-duplicate-keys" "^7.18.9" "@babel/plugin-transform-exponentiation-operator" "^7.18.6" @@ -1091,9 +1092,9 @@ "@babel/plugin-transform-member-expression-literals" "^7.18.6" "@babel/plugin-transform-modules-amd" "^7.18.6" "@babel/plugin-transform-modules-commonjs" "^7.18.6" - "@babel/plugin-transform-modules-systemjs" "^7.18.9" + "@babel/plugin-transform-modules-systemjs" "^7.19.0" "@babel/plugin-transform-modules-umd" "^7.18.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.0" "@babel/plugin-transform-new-target" "^7.18.6" "@babel/plugin-transform-object-super" "^7.18.6" "@babel/plugin-transform-parameters" "^7.18.8" @@ -1101,14 +1102,14 @@ "@babel/plugin-transform-regenerator" "^7.18.6" "@babel/plugin-transform-reserved-words" "^7.18.6" "@babel/plugin-transform-shorthand-properties" "^7.18.6" - "@babel/plugin-transform-spread" "^7.18.9" + "@babel/plugin-transform-spread" "^7.19.0" "@babel/plugin-transform-sticky-regex" "^7.18.6" "@babel/plugin-transform-template-literals" "^7.18.9" "@babel/plugin-transform-typeof-symbol" "^7.18.9" "@babel/plugin-transform-unicode-escapes" "^7.18.10" "@babel/plugin-transform-unicode-regex" "^7.18.6" "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.18.10" + "@babel/types" "^7.19.0" babel-plugin-polyfill-corejs2 "^0.3.2" babel-plugin-polyfill-corejs3 "^0.5.3" babel-plugin-polyfill-regenerator "^0.4.0" @@ -1174,10 +1175,10 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.0", "@babel/runtime@^7.18.9", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" - integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.0", "@babel/runtime@^7.19.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" + integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== dependencies: regenerator-runtime "^0.13.4" @@ -1190,26 +1191,26 @@ "@babel/parser" "^7.18.10" "@babel/types" "^7.18.10" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.3", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.18.13", "@babel/traverse@^7.18.9", "@babel/traverse@^7.4.5": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.13.tgz#5ab59ef51a997b3f10c4587d648b9696b6cb1a68" - integrity sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.3", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.18.9", "@babel/traverse@^7.19.0", "@babel/traverse@^7.4.5": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.0.tgz#eb9c561c7360005c592cc645abafe0c3c4548eed" + integrity sha512-4pKpFRDh+utd2mbRC8JLnlsMUii3PMHjpL6a0SZ4NMZy7YFP9aXORxEhdMVOc9CpWtDF09IkciQLEhK7Ml7gRA== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.18.13" + "@babel/generator" "^7.19.0" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.18.13" - "@babel/types" "^7.18.13" + "@babel/parser" "^7.19.0" + "@babel/types" "^7.19.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.10.3", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.18.10", "@babel/types@^7.18.13", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.13.tgz#30aeb9e514f4100f7c1cb6e5ba472b30e48f519a" - integrity sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ== +"@babel/types@^7.0.0", "@babel/types@^7.10.3", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" + integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA== dependencies: "@babel/helper-string-parser" "^7.18.10" "@babel/helper-validator-identifier" "^7.18.6" @@ -9128,7 +9129,7 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7, accepts@~1.3.8: +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -10384,22 +10385,6 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - body-parser@1.19.2: version "1.19.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e" @@ -10826,11 +10811,6 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -11833,13 +11813,6 @@ container-info@^1.0.1: resolved "https://registry.yarnpkg.com/container-info/-/container-info-1.0.1.tgz#6b383cb5e197c8d921e88983388facb04124b56b" integrity sha512-wk/+uJvPHOFG+JSwQS+fw6H6yw3Oyc8Kw9L4O2MN817uA90OqJ59nlZbbLPqDudsjJ7Tetee3pwExdKpd2ahjQ== -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - content-disposition@0.5.4, content-disposition@^0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -11876,11 +11849,6 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - cookie@0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" @@ -14746,43 +14714,7 @@ expose-loader@^0.7.5: resolved "https://registry.yarnpkg.com/expose-loader/-/expose-loader-0.7.5.tgz#e29ea2d9aeeed3254a3faa1b35f502db9f9c3f6f" integrity sha512-iPowgKUZkTPX5PznYsmifVj9Bob0w2wTHVkt/eYNPSzyebkUgIedmskf/kcfEIWpiWjg3JRjnW+a17XypySMuw== -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -express@^4.17.3: +express@^4.17.1, express@^4.17.3: version "4.17.3" resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1" integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg== @@ -15623,12 +15555,7 @@ geckodriver@^3.0.2: https-proxy-agent "5.0.0" tar "6.1.11" -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== - -gensync@^1.0.0-beta.2: +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -16686,17 +16613,6 @@ http-deceiver@^1.2.7: resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= -http-errors@1.7.2, http-errors@~1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-errors@1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" @@ -22667,7 +22583,7 @@ protocol-buffers-schema@^3.3.1: resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz#00434f608b4e8df54c59e070efeefc37fb4bb859" integrity sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w== -proxy-addr@~2.0.5, proxy-addr@~2.0.7: +proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -22800,11 +22716,6 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - qs@6.9.7: version "6.9.7" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" @@ -22935,16 +22846,6 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-body@2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c" @@ -24824,25 +24725,6 @@ semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semve dependencies: lru-cache "^6.0.0" -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - send@0.17.2: version "0.17.2" resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" @@ -24907,16 +24789,6 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - serve-static@1.14.2: version "1.14.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" @@ -24977,11 +24849,6 @@ setprototypeof@1.1.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" @@ -26198,15 +26065,7 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-hyperlinks@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz#f663df252af5f37c5d49bbd7eeefa9e0b9e59e47" - integrity sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA== - dependencies: - has-flag "^4.0.0" - supports-color "^7.0.0" - -supports-hyperlinks@^2.2.0: +supports-hyperlinks@^2.0.0, supports-hyperlinks@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== @@ -26746,11 +26605,6 @@ toggle-selection@^1.0.6: resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -27041,7 +26895,7 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.17, type-is@~1.6.18: +type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -28658,7 +28512,7 @@ windows-release@^3.1.0: dependencies: execa "^1.0.0" -winston-transport@^4.4.2, winston-transport@^4.5.0: +winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== @@ -28667,23 +28521,7 @@ winston-transport@^4.4.2, winston-transport@^4.5.0: readable-stream "^3.6.0" triple-beam "^1.3.0" -winston@^3.3.3: - version "3.5.1" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.5.1.tgz#b25cc899d015836dbf8c583dec8c4c4483a0da2e" - integrity sha512-tbRtVy+vsSSCLcZq/8nXZaOie/S2tPXPFt4be/Q3vI/WtYwm7rrwidxVw2GRa38FIXcJ1kUM6MOZ9Jmnk3F3UA== - dependencies: - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.3.2" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.4.2" - -winston@^3.8.1: +winston@^3.3.3, winston@^3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/winston/-/winston-3.8.1.tgz#76f15b3478cde170b780234e0c4cf805c5a7fb57" integrity sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w== From e838bb6dc8e7214527d2759b700bace91c7c11ed Mon Sep 17 00:00:00 2001 From: Justin Kambic <jk@elastic.co> Date: Tue, 13 Sep 2022 00:04:04 -0400 Subject: [PATCH 090/144] [Synthetics] Add Enabled toggle to monitor add/edit form (#140125) * Add enabled feature to add/edit page. * Update tests for new logic. * Move enabled form field to bottom of group. * Change copy to correspond to updated description. * Fix punctuation. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../monitor_add_edit/form/field_config.tsx | 22 +++ .../monitor_add_edit/form/form_config.tsx | 5 + .../monitor_add_edit/form/formatter.test.tsx | 144 +++++++++--------- .../monitor_add_edit/form/formatter.ts | 2 +- 4 files changed, 102 insertions(+), 71 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx index b3d7f10c2b7b53..1220c50456bb48 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx @@ -411,6 +411,28 @@ export const FIELD: Record<string, FieldMeta> = { }; }, }, + [ConfigKey.ENABLED]: { + fieldKey: ConfigKey.ENABLED, + component: EuiSwitch, + label: i18n.translate('xpack.synthetics.monitorConfig.enabled.label', { + defaultMessage: 'Enable Monitor', + }), + controlled: true, + props: ({ isEdit, setValue }) => ({ + id: 'syntheticsMontiorConfigIsEnabled', + label: isEdit + ? i18n.translate('xpack.synthetics.monitorConfig.edit.enabled.label', { + defaultMessage: 'Disabled monitors do not run tests.', + }) + : i18n.translate('xpack.synthetics.monitorConfig.create.enabled.label', { + defaultMessage: + 'Disabled monitors do not run tests. You can create a disabled monitor and enable it later.', + }), + onChange: (event: React.ChangeEvent<HTMLInputElement>) => { + setValue(ConfigKey.ENABLED, !!event.target.checked); + }, + }), + }, [ConfigKey.TAGS]: { fieldKey: ConfigKey.TAGS, component: ComboBox, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx index 1c49665af081eb..9f11f2c53c06e5 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx @@ -149,6 +149,7 @@ export const FORM_CONFIG: FieldConfig = { FIELD[ConfigKey.SCHEDULE], FIELD[ConfigKey.MAX_REDIRECTS], FIELD[ConfigKey.TIMEOUT], + FIELD[ConfigKey.ENABLED], ], advanced: [ DEFAULT_DATA_OPTIONS, @@ -166,6 +167,7 @@ export const FORM_CONFIG: FieldConfig = { FIELD[ConfigKey.LOCATIONS], FIELD[ConfigKey.SCHEDULE], FIELD[ConfigKey.TIMEOUT], + FIELD[ConfigKey.ENABLED], ], advanced: [ DEFAULT_DATA_OPTIONS, @@ -181,6 +183,7 @@ export const FORM_CONFIG: FieldConfig = { FIELD[ConfigKey.LOCATIONS], FIELD[ConfigKey.SCHEDULE], FIELD[ConfigKey.THROTTLING_CONFIG], + FIELD[ConfigKey.ENABLED], ], step3: [FIELD[ConfigKey.SOURCE_INLINE]], scriptEdit: [FIELD[ConfigKey.SOURCE_INLINE]], @@ -205,6 +208,7 @@ export const FORM_CONFIG: FieldConfig = { FIELD[ConfigKey.LOCATIONS], FIELD[ConfigKey.SCHEDULE], FIELD[ConfigKey.THROTTLING_CONFIG], + FIELD[ConfigKey.ENABLED], ], advanced: [ { @@ -227,6 +231,7 @@ export const FORM_CONFIG: FieldConfig = { FIELD[ConfigKey.SCHEDULE], FIELD[ConfigKey.WAIT], FIELD[ConfigKey.TIMEOUT], + FIELD[ConfigKey.ENABLED], ], advanced: [DEFAULT_DATA_OPTIONS], }, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx index 80b34b47fdc9f1..1cf2baf1df94f1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.test.tsx @@ -8,81 +8,85 @@ import { format } from './formatter'; describe('format', () => { - const formValues = { - type: 'http', - form_monitor_type: 'http', - enabled: true, - schedule: { - number: '3', - unit: 'm', - }, - 'service.name': '', - tags: [], - timeout: '16', - name: 'Sample name', - locations: [ - { - id: 'us_central', - isServiceManaged: true, + let formValues: Record<string, unknown>; + beforeEach(() => { + formValues = { + type: 'http', + form_monitor_type: 'http', + enabled: true, + schedule: { + number: '3', + unit: 'm', }, - ], - namespace: 'default', - origin: 'ui', - __ui: { - is_tls_enabled: false, - }, - urls: 'sample url', - max_redirects: '0', - password: '', - proxy_url: '', - 'check.response.body.negative': [], - 'check.response.body.positive': [], - 'response.include_body': 'on_error', - 'check.response.headers': {}, - 'response.include_headers': true, - 'check.response.status': [], - 'check.request.body': { - value: '', - type: 'text', - }, - 'check.request.headers': {}, - 'check.request.method': 'GET', - username: '', - 'ssl.certificate_authorities': '', - 'ssl.certificate': '', - 'ssl.key': '', - 'ssl.key_passphrase': '', - 'ssl.verification_mode': 'full', - 'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], - isTLSEnabled: false, - service: { - name: '', - }, - check: { - request: { - method: 'GET', - headers: {}, - body: { - type: 'text', - value: '', + 'service.name': '', + tags: [], + timeout: '16', + name: 'Sample name', + locations: [ + { + id: 'us_central', + isServiceManaged: true, }, + ], + namespace: 'default', + origin: 'ui', + __ui: { + is_tls_enabled: false, }, - response: { - status: [], - headers: {}, - body: { - positive: [], - negative: [], + urls: 'sample url', + max_redirects: '0', + password: '', + proxy_url: '', + 'check.response.body.negative': [], + 'check.response.body.positive': [], + 'response.include_body': 'on_error', + 'check.response.headers': {}, + 'response.include_headers': true, + 'check.response.status': [], + 'check.request.body': { + value: '', + type: 'text', + }, + 'check.request.headers': {}, + 'check.request.method': 'GET', + username: '', + 'ssl.certificate_authorities': '', + 'ssl.certificate': '', + 'ssl.key': '', + 'ssl.key_passphrase': '', + 'ssl.verification_mode': 'full', + 'ssl.supported_protocols': ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], + isTLSEnabled: false, + service: { + name: '', + }, + check: { + request: { + method: 'GET', + headers: {}, + body: { + type: 'text', + value: '', + }, }, + response: { + status: [], + headers: {}, + body: { + positive: [], + negative: [], + }, + }, + }, + response: { + include_headers: true, + include_body: 'on_error', }, - }, - response: { - include_headers: true, - include_body: 'on_error', - }, - }; + }; + }); - it('correctly formats form fields to monitor type', () => { + it.each([[true], [false]])('correctly formats form fields to monitor type', (enabled) => { + formValues.enabled = enabled; expect(format(formValues)).toEqual({ __ui: { is_tls_enabled: false, @@ -98,7 +102,7 @@ describe('format', () => { 'check.response.body.positive': [], 'check.response.headers': {}, 'check.response.status': [], - enabled: true, + enabled, form_monitor_type: 'http', locations: [ { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.ts index 8da53f6cbb2806..3495e0104e852c 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/formatter.ts @@ -15,7 +15,7 @@ export const formatter = (fields: Record<string, any>) => { Object.keys(defaults).map((key) => { /* split key names on dot to handle dot notation fields, * which are changed to nested fields by react-hook-form */ - monitorFields[key] = get(fields, key.split('.')) || defaults[key as ConfigKey]; + monitorFields[key] = get(fields, key.split('.')) ?? defaults[key as ConfigKey]; }); return monitorFields as MonitorFields; }; From c9628fc0bebba0f51418d522ea62a72257c37cb8 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 12 Sep 2022 22:39:30 -0600 Subject: [PATCH 091/144] [api-docs] Daily api_docs build (#140566) --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 2 +- api_docs/apm.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.devdocs.json | 12 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/core.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.devdocs.json | 4 +- api_docs/data.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.devdocs.json | 444 ++++++++++++++---- api_docs/data_view_field_editor.mdx | 4 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.devdocs.json | 130 ++++- api_docs/data_views.mdx | 4 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 2 +- api_docs/deprecations_by_plugin.mdx | 2 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_log.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/fleet.devdocs.json | 153 ++++-- api_docs/fleet.mdx | 4 +- api_docs/global_search.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_utils.mdx | 2 +- api_docs/kbn_alerts.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_client.mdx | 2 +- ..._analytics_shippers_elastic_v3_browser.mdx | 2 +- ...n_analytics_shippers_elastic_v3_common.mdx | 2 +- ...n_analytics_shippers_elastic_v3_server.mdx | 2 +- api_docs/kbn_analytics_shippers_fullstory.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- .../kbn_core_injected_metadata_browser.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...core_saved_objects_api_server_internal.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_internal.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_get_repo_files.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- ...hared_ux_button_exit_full_screen_mocks.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_package_json.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_type_summarizer.mdx | 2 +- api_docs/kbn_type_summarizer_core.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.devdocs.json | 28 ++ api_docs/lens.mdx | 4 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 16 +- api_docs/presentation_util.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.devdocs.json | 71 +++ api_docs/rule_registry.mdx | 4 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/security.mdx | 2 +- api_docs/security_solution.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/task_manager.devdocs.json | 28 +- api_docs/task_manager.mdx | 4 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_field_list.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 390 files changed, 1097 insertions(+), 563 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index e89fd0e7ed367d..d68db98936249d 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index a6de0eddd53d61..a1ca756a109b8c 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index db20b98ed0f6a5..9cd9f8e457d68c 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index d46ff5aa181b59..c204e11c5f354b 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 371251c3d2f6bc..c46f1df7d58a0c 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 48441c7541f204..058410350bba1e 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index 051acd0e759002..45354e97c4a872 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index a0952458e0f453..bdb2bfdfb57f63 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.devdocs.json b/api_docs/cases.devdocs.json index e68be19ab72037..b6707b75f20547 100644 --- a/api_docs/cases.devdocs.json +++ b/api_docs/cases.devdocs.json @@ -1544,7 +1544,7 @@ "ConnectorTypes", ".swimlane; fields: { caseId: string | null; } | null; name: string; }; settings: { syncAlerts: boolean; }; owner: string; severity: ", "CaseSeverity", - "; assignees: { uid: string; }[]; duration: number | null; closedAt: string | null; closedBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; } | null; createdAt: string; createdBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; }; externalService: { connectorId: string; connectorName: string; externalId: string; externalTitle: string; externalUrl: string; pushedAt: string; pushedBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; }; } | null; updatedAt: string | null; updatedBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; } | null; id: string; totalComment: number; totalAlerts: number; version: string; comments?: ((({ comment: string; type: ", + "; assignees: { uid: string; }[]; duration: number | null; closedAt: string | null; closedBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; profileUid?: string | undefined; } | null; createdAt: string; createdBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; profileUid?: string | undefined; }; externalService: { connectorId: string; connectorName: string; externalId: string; externalTitle: string; externalUrl: string; pushedAt: string; pushedBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; profileUid?: string | undefined; }; } | null; updatedAt: string | null; updatedBy: { email: string | null | undefined; fullName: string | null | undefined; username: string | null | undefined; profileUid?: string | undefined; } | null; id: string; totalComment: number; totalAlerts: number; version: string; comments?: ((({ comment: string; type: ", { "pluginId": "cases", "scope": "common", @@ -1552,7 +1552,7 @@ "section": "def-common.CommentType", "text": "CommentType" }, - ".user; owner: string; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; }; owner: string; pushed_at: string | null; pushed_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; updated_at: string | null; updated_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; }) | ({ type: ", + ".user; owner: string; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }; owner: string; pushed_at: string | null; pushed_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; updated_at: string | null; updated_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; }) | ({ type: ", { "pluginId": "cases", "scope": "common", @@ -1560,7 +1560,7 @@ "section": "def-common.CommentType", "text": "CommentType" }, - ".alert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; }; owner: string; pushed_at: string | null; pushed_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; updated_at: string | null; updated_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; }) | ({ type: ", + ".alert; alertId: string | string[]; index: string | string[]; rule: { id: string | null; name: string | null; }; owner: string; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }; owner: string; pushed_at: string | null; pushed_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; updated_at: string | null; updated_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; }) | ({ type: ", { "pluginId": "cases", "scope": "common", @@ -1568,7 +1568,7 @@ "section": "def-common.CommentType", "text": "CommentType" }, - ".actions; comment: string; actions: { targets: { hostname: string; endpointId: string; }[]; type: string; }; owner: string; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; }; owner: string; pushed_at: string | null; pushed_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; updated_at: string | null; updated_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; }) | (({ externalReferenceId: string; externalReferenceStorage: { type: ", + ".actions; comment: string; actions: { targets: { hostname: string; endpointId: string; }[]; type: string; }; owner: string; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }; owner: string; pushed_at: string | null; pushed_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; updated_at: string | null; updated_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; }) | (({ externalReferenceId: string; externalReferenceStorage: { type: ", "ExternalReferenceStorageType", ".elasticSearchDoc; }; externalReferenceAttachmentTypeId: string; externalReferenceMetadata: { [x: string]: ", "JsonValue", @@ -1592,7 +1592,7 @@ "section": "def-common.CommentType", "text": "CommentType" }, - ".externalReference; owner: string; }) & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; }; owner: string; pushed_at: string | null; pushed_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; updated_at: string | null; updated_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; }) | ({ type: ", + ".externalReference; owner: string; }) & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }; owner: string; pushed_at: string | null; pushed_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; updated_at: string | null; updated_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; }) | ({ type: ", { "pluginId": "cases", "scope": "common", @@ -1602,7 +1602,7 @@ }, ".persistableState; owner: string; persistableStateAttachmentTypeId: string; persistableStateAttachmentState: { [x: string]: ", "JsonValue", - "; }; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; }; owner: string; pushed_at: string | null; pushed_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; updated_at: string | null; updated_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } | null; })) & { id: string; version: string; })[] | undefined; }, \"comments\"> & { comments: ", + "; }; } & { created_at: string; created_by: { email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }; owner: string; pushed_at: string | null; pushed_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; updated_at: string | null; updated_by: ({ email: string | null | undefined; full_name: string | null | undefined; username: string | null | undefined; } & { profile_uid?: string | undefined; }) | null; })) & { id: string; version: string; })[] | undefined; }, \"comments\"> & { comments: ", "Comment", "[]; }" ], diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index dbd163dff3005e..15ac5bbe960305 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 94a6853c57cce2..9da2543d3f733a 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 67f888cd10fab7..66d95d63ab7c8f 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 2d93e7b6a7ef6c..a4273432acce65 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 885e264937e68f..9232c9a652e8b0 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 07fbe27b7c0486..f708eefcfcfabf 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/core.mdx b/api_docs/core.mdx index 9d6e7827173248..43ae9b642053fd 100644 --- a/api_docs/core.mdx +++ b/api_docs/core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/core title: "core" image: https://source.unsplash.com/400x175/?github description: API docs for the core plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'core'] --- import coreObj from './core.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 604f24762a12bc..f209b146be305b 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 454aa521d59424..1d1919aa011f37 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 125f6303237f39..325517a508ef27 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index bd569dc580afc5..08e02ccff050f9 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -20274,7 +20274,7 @@ "section": "def-common.RuntimeFieldSpec", "text": "RuntimeFieldSpec" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; }" + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" ], "path": "src/plugins/data_views/common/fields/data_view_field.ts", "deprecated": false, @@ -24594,7 +24594,7 @@ "section": "def-common.RuntimeFieldSpec", "text": "RuntimeFieldSpec" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; }" + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, diff --git a/api_docs/data.mdx b/api_docs/data.mdx index bb06789a9d338b..79520620b1eb81 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index e862a2588c40d4..5862b9b6a1092e 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index 247b776e53e307..d98fcbe787af6b 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 594122e246d100..7670465e813153 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.devdocs.json b/api_docs/data_view_field_editor.devdocs.json index 7843f117d57e9e..50c48bbe6aed25 100644 --- a/api_docs/data_view_field_editor.devdocs.json +++ b/api_docs/data_view_field_editor.devdocs.json @@ -26,7 +26,13 @@ "text": "FormatEditorProps" }, "<P>, ", - "FormatEditorState", + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.FormatEditorState", + "text": "FormatEditorState" + }, " & S, any>" ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx", @@ -52,7 +58,13 @@ "label": "state", "description": [], "signature": [ - "FormatEditorState", + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.FormatEditorState", + "text": "FormatEditorState" + }, " & S" ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx", @@ -76,9 +88,21 @@ "text": "FormatEditorProps" }, "<{}>, state: ", - "FormatEditorState", + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.FormatEditorState", + "text": "FormatEditorState" + }, ") => { error: string | undefined; samples: ", - "Sample", + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.Sample", + "text": "Sample" + }, "[]; }" ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx", @@ -115,7 +139,13 @@ "label": "state", "description": [], "signature": [ - "FormatEditorState" + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.FormatEditorState", + "text": "FormatEditorState" + } ], "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/editors/default/default.tsx", "deprecated": false, @@ -175,6 +205,64 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.DeleteCompositeSubfield", + "type": "Class", + "tags": [], + "label": "DeleteCompositeSubfield", + "description": [ + "\nError throw when there's an attempt to directly delete a composite subfield" + ], + "signature": [ + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.DeleteCompositeSubfield", + "text": "DeleteCompositeSubfield" + }, + " extends Error" + ], + "path": "src/plugins/data_view_field_editor/public/open_delete_modal.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.DeleteCompositeSubfield.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "src/plugins/data_view_field_editor/public/open_delete_modal.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.DeleteCompositeSubfield.Unnamed.$1", + "type": "string", + "tags": [], + "label": "fieldName", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/data_view_field_editor/public/open_delete_modal.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false } ], "functions": [], @@ -188,6 +276,23 @@ "description": [ "\nThe data model for the field editor" ], + "signature": [ + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.Field", + "text": "Field" + }, + " extends ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + } + ], "path": "src/plugins/data_view_field_editor/public/types.ts", "deprecated": false, "trackAdoption": false, @@ -207,44 +312,12 @@ }, { "parentPluginId": "dataViewFieldEditor", - "id": "def-public.Field.type", - "type": "CompoundType", - "tags": [], - "label": "type", - "description": [ - "\nES type" - ], - "signature": [ - "\"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"geo_point\" | \"long\" | \"double\" | \"composite\"" - ], - "path": "src/plugins/data_view_field_editor/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViewFieldEditor", - "id": "def-public.Field.script", - "type": "Object", - "tags": [], - "label": "script", - "description": [ - "\nsource of the runtime field script" - ], - "signature": [ - "{ source: string; } | undefined" - ], - "path": "src/plugins/data_view_field_editor/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViewFieldEditor", - "id": "def-public.Field.customLabel", + "id": "def-public.Field.parentName", "type": "string", "tags": [], - "label": "customLabel", + "label": "parentName", "description": [ - "\ncustom label for display" + "\nName of parent field. Used for composite subfields" ], "signature": [ "string | undefined" @@ -252,47 +325,6 @@ "path": "src/plugins/data_view_field_editor/public/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "dataViewFieldEditor", - "id": "def-public.Field.popularity", - "type": "number", - "tags": [], - "label": "popularity", - "description": [ - "\ncustom popularity" - ], - "signature": [ - "number | undefined" - ], - "path": "src/plugins/data_view_field_editor/public/types.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "dataViewFieldEditor", - "id": "def-public.Field.format", - "type": "Object", - "tags": [], - "label": "format", - "description": [ - "\nconfiguration of the field format" - ], - "signature": [ - { - "pluginId": "fieldFormats", - "scope": "common", - "docId": "kibFieldFormatsPluginApi", - "section": "def-common.SerializedFieldFormat", - "text": "SerializedFieldFormat" - }, - "<{}, ", - "SerializableRecord", - "> | undefined" - ], - "path": "src/plugins/data_view_field_editor/public/types.ts", - "deprecated": false, - "trackAdoption": false } ], "initialIsOpen": false @@ -433,13 +465,65 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.FormatEditorState", + "type": "Interface", + "tags": [], + "label": "FormatEditorState", + "description": [], + "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.FormatEditorState.EditorComponent", + "type": "CompoundType", + "tags": [], + "label": "EditorComponent", + "description": [], + "signature": [ + "React.LazyExoticComponent<", + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.FieldFormatEditor", + "text": "FieldFormatEditor" + }, + "<{}>> | null" + ], + "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.FormatEditorState.fieldFormatId", + "type": "string", + "tags": [], + "label": "fieldFormatId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/format_editor.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "dataViewFieldEditor", "id": "def-public.OpenFieldDeleteModalOptions", "type": "Interface", "tags": [], "label": "OpenFieldDeleteModalOptions", - "description": [], + "description": [ + "\nOptions for opening the field editor" + ], "path": "src/plugins/data_view_field_editor/public/open_delete_modal.tsx", "deprecated": false, "trackAdoption": false, @@ -450,7 +534,9 @@ "type": "Object", "tags": [], "label": "ctx", - "description": [], + "description": [ + "\nConfig for the delete modal" + ], "signature": [ "{ dataView: ", { @@ -472,7 +558,9 @@ "type": "Function", "tags": [], "label": "onDelete", - "description": [], + "description": [ + "\nCallback fired when fields are deleted" + ], "signature": [ "((fieldNames: string[]) => void) | undefined" ], @@ -486,7 +574,9 @@ "type": "Array", "tags": [], "label": "fieldNames", - "description": [], + "description": [ + "- the names of the deleted fields" + ], "signature": [ "string[]" ], @@ -504,7 +594,9 @@ "type": "CompoundType", "tags": [], "label": "fieldName", - "description": [], + "description": [ + "\nNames of the fields to be deleted" + ], "signature": [ "string | string[]" ], @@ -570,7 +662,7 @@ "section": "def-common.DataViewField", "text": "DataViewField" }, - ") => void) | undefined" + "[]) => void) | undefined" ], "path": "src/plugins/data_view_field_editor/public/open_editor.tsx", "deprecated": false, @@ -579,10 +671,12 @@ { "parentPluginId": "dataViewFieldEditor", "id": "def-public.OpenFieldEditorOptions.onSave.$1", - "type": "Object", + "type": "Array", "tags": [], "label": "field", - "description": [], + "description": [ + "- the fields that were saved" + ], "signature": [ { "pluginId": "dataViews", @@ -590,7 +684,8 @@ "docId": "kibDataViewsPluginApi", "section": "def-common.DataViewField", "text": "DataViewField" - } + }, + "[]" ], "path": "src/plugins/data_view_field_editor/public/open_editor.tsx", "deprecated": false, @@ -641,6 +736,149 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Props", + "type": "Interface", + "tags": [], + "label": "Props", + "description": [], + "path": "src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Props.children", + "type": "Function", + "tags": [], + "label": "children", + "description": [], + "signature": [ + "(deleteFieldHandler: DeleteFieldFunc) => React.ReactNode" + ], + "path": "src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Props.children.$1", + "type": "Function", + "tags": [], + "label": "deleteFieldHandler", + "description": [], + "signature": [ + "DeleteFieldFunc" + ], + "path": "src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Props.dataView", + "type": "Object", + "tags": [], + "label": "dataView", + "description": [ + "\nData view of fields to be deleted" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.DataView", + "text": "DataView" + } + ], + "path": "src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Props.onDelete", + "type": "Function", + "tags": [], + "label": "onDelete", + "description": [ + "\nCallback fired when fields are deleted" + ], + "signature": [ + "((fieldNames: string[]) => void) | undefined" + ], + "path": "src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Props.onDelete.$1", + "type": "Array", + "tags": [], + "label": "fieldNames", + "description": [ + "- the names of the deleted fields" + ], + "signature": [ + "string[]" + ], + "path": "src/plugins/data_view_field_editor/public/components/delete_field_provider.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Sample", + "type": "Interface", + "tags": [], + "label": "Sample", + "description": [], + "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Sample.input", + "type": "CompoundType", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "object | React.ReactText | React.ReactText[] | Record<string, React.ReactText[]>" + ], + "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "dataViewFieldEditor", + "id": "def-public.Sample.output", + "type": "string", + "tags": [], + "label": "output", + "description": [], + "path": "src/plugins/data_view_field_editor/public/components/field_format_editor/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false } ], "enums": [], @@ -758,7 +996,7 @@ "tags": [], "label": "openEditor", "description": [ - "\nmethod to open the data view field editor fly-out" + "\nMethod to open the data view field editor fly-out" ], "signature": [ "(options: ", @@ -805,7 +1043,9 @@ "type": "Function", "tags": [], "label": "openDeleteModal", - "description": [], + "description": [ + "\nMethod to open the data view field delete fly-out" + ], "signature": [ "(options: ", { @@ -827,7 +1067,9 @@ "type": "Object", "tags": [], "label": "options", - "description": [], + "description": [ + "Configuration options for the fly-out" + ], "signature": [ { "pluginId": "dataViewFieldEditor", @@ -881,7 +1123,9 @@ "type": "Object", "tags": [], "label": "userPermissions", - "description": [], + "description": [ + "\nConvenience method for user permissions checks" + ], "signature": [ "{ editIndexPattern: () => boolean; }" ], @@ -895,10 +1139,18 @@ "type": "Function", "tags": [], "label": "DeleteRuntimeFieldProvider", - "description": [], + "description": [ + "\nContext provider for delete runtime field modal" + ], "signature": [ "React.FunctionComponent<", - "Props", + { + "pluginId": "dataViewFieldEditor", + "scope": "public", + "docId": "kibDataViewFieldEditorPluginApi", + "section": "def-public.Props", + "text": "Props" + }, ">" ], "path": "src/plugins/data_view_field_editor/public/types.ts", diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 2881eb78d6fbdb..2232f402be5aaa 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 49 | 0 | 29 | 3 | +| 60 | 0 | 30 | 0 | ## Client diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index fe964392680cd0..ba449bf7a8e585 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index 389500b91049cd..9367e3045535b6 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -1705,7 +1705,7 @@ "section": "def-common.RuntimeFieldSpec", "text": "RuntimeFieldSpec" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; }" + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" ], "path": "src/plugins/data_views/common/fields/data_view_field.ts", "deprecated": false, @@ -5936,6 +5936,70 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "dataViews", + "id": "def-public.RuntimeField", + "type": "Interface", + "tags": [], + "label": "RuntimeField", + "description": [ + "\nThis is the RuntimeField interface enhanced with Data view field\nconfiguration: field format definition, customLabel or popularity." + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeField", + "text": "RuntimeField" + }, + " extends ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeFieldBase", + "text": "RuntimeFieldBase" + }, + ",", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.FieldConfiguration", + "text": "FieldConfiguration" + } + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "dataViews", + "id": "def-public.RuntimeField.fields", + "type": "Object", + "tags": [], + "label": "fields", + "description": [ + "\nSubfields of composite field" + ], + "signature": [ + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeFieldSubFields", + "text": "RuntimeFieldSubFields" + }, + " | undefined" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "dataViews", "id": "def-public.SavedObjectsClientCommon", @@ -6454,7 +6518,7 @@ "section": "def-common.RuntimeFieldSpec", "text": "RuntimeFieldSpec" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; }" + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, @@ -6536,7 +6600,7 @@ "tags": [], "label": "RuntimeType", "description": [ - "\nRuntime field - type of value returned" + "\nRuntime field types" ], "signature": [ "\"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"geo_point\" | \"long\" | \"double\" | \"composite\"" @@ -11114,7 +11178,7 @@ "section": "def-common.RuntimeFieldSpec", "text": "RuntimeFieldSpec" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; }" + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, @@ -14365,7 +14429,7 @@ "section": "def-common.RuntimeFieldSpec", "text": "RuntimeFieldSpec" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; }" + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" ], "path": "src/plugins/data_views/common/fields/data_view_field.ts", "deprecated": false, @@ -19607,15 +19671,14 @@ "\nSubfields of composite field" ], "signature": [ - "Record<string, ", { "pluginId": "dataViews", "scope": "common", "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeFieldSubField", - "text": "RuntimeFieldSubField" + "section": "def-common.RuntimeFieldSubFields", + "text": "RuntimeFieldSubFields" }, - "> | undefined" + " | undefined" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, @@ -19660,9 +19723,7 @@ "type": "CompoundType", "tags": [], "label": "type", - "description": [ - "\nType of runtime field, can only be primitive type" - ], + "description": [], "signature": [ "\"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"geo_point\" | \"long\" | \"double\"" ], @@ -21094,7 +21155,7 @@ "section": "def-common.RuntimeFieldSpec", "text": "RuntimeFieldSpec" }, - " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; }" + " | undefined; fixedInterval?: string[] | undefined; timeZone?: string[] | undefined; timeSeriesDimension?: boolean | undefined; timeSeriesMetric?: \"gauge\" | \"histogram\" | \"summary\" | \"counter\" | undefined; shortDotsEnable?: boolean | undefined; isMapped?: boolean | undefined; parentName?: string | undefined; }" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, @@ -21336,8 +21397,8 @@ "pluginId": "dataViews", "scope": "common", "docId": "kibDataViewsPluginApi", - "section": "def-common.RuntimeTypeExceptComposite", - "text": "RuntimeTypeExceptComposite" + "section": "def-common.RuntimePrimitiveTypes", + "text": "RuntimePrimitiveTypes" }, "; }> | undefined; }" ], @@ -21348,15 +21409,38 @@ }, { "parentPluginId": "dataViews", - "id": "def-common.RuntimeType", + "id": "def-common.RuntimeFieldSubFields", "type": "Type", "tags": [], - "label": "RuntimeType", + "label": "RuntimeFieldSubFields", + "description": [], + "signature": [ + "{ [x: string]: ", + { + "pluginId": "dataViews", + "scope": "common", + "docId": "kibDataViewsPluginApi", + "section": "def-common.RuntimeFieldSubField", + "text": "RuntimeFieldSubField" + }, + "; }" + ], + "path": "src/plugins/data_views/common/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "dataViews", + "id": "def-common.RuntimePrimitiveTypes", + "type": "Type", + "tags": [], + "label": "RuntimePrimitiveTypes", "description": [ - "\nRuntime field - type of value returned" + "\nRuntime field primitive types - excluding composite" ], "signature": [ - "\"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"geo_point\" | \"long\" | \"double\" | \"composite\"" + "\"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"geo_point\" | \"long\" | \"double\"" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, @@ -21365,15 +21449,15 @@ }, { "parentPluginId": "dataViews", - "id": "def-common.RuntimeTypeExceptComposite", + "id": "def-common.RuntimeType", "type": "Type", "tags": [], - "label": "RuntimeTypeExceptComposite", + "label": "RuntimeType", "description": [ - "\nPrimitive runtime field types" + "\nRuntime field types" ], "signature": [ - "\"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"geo_point\" | \"long\" | \"double\"" + "\"boolean\" | \"date\" | \"keyword\" | \"ip\" | \"geo_point\" | \"long\" | \"double\" | \"composite\"" ], "path": "src/plugins/data_views/common/types.ts", "deprecated": false, diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 35957ede2cc4fb..959042fc63b916 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; @@ -21,7 +21,7 @@ Contact [App Services](https://github.com/orgs/elastic/teams/kibana-app-services | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 963 | 0 | 206 | 1 | +| 966 | 0 | 208 | 1 | ## Client diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 63c9c3051d4e40..b1520fe7a33e63 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index d9ba036f7bbe64..d76f1607ad1885 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 07f70de66a166b..199872dc950416 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 4a9e44b189a791..0848e13dbed6b8 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 6ab2af56de8a69..edd78a33faaa4c 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index c21e6fc7a14bd0..5ee6a5d63ba40d 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 844946af12dba9..3ee8e184d8ddcc 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 6d0f630e840481..91f52a2f8c585e 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index cf1334edf5db33..69da5e958b04e2 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 31c161302239c3..0dbb09172151ca 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 337602bc8deb6e..f743ff7a1df04e 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 88767bde098f93..c9bad1151010f9 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index bfb01ed547536b..c373e6ced0e247 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 67fc800a393f54..8b17841c88af29 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index 55e41dee84df05..beaaa9c75b73cf 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 272f14fa331c1b..98e645c40c3d2c 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 883e69752d7c20..e5c0a4f72c3618 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 2fd851509964a8..6d49bbc381aeff 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index dd3e3a7c1b9c4b..7ab985cb8cdbf1 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index ec3bd2846e1a8a..8ac69b55c3af17 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index 323af21664b16a..192fbd7b5696ef 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index ce8b70c802891c..56c995e98b69af 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 44d11e482c8992..278c1fa36331a0 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 170818628b752f..7a63d138d0df61 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index ba84f73e3531a0..3f3b8bc6370c15 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index a1190ad13be1af..6c2bca0d28e616 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index e58dcecd23eb3d..511984dd0fc87b 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index be939038342854..a202ce1aa6a700 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 7084d5dd8614b8..235658be3b78da 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index a3a2ffc66d7248..6ac6cf2ecdeefa 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 5acb5094dcbe3f..da61befcf587aa 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index d2657f32584525..314f463c007de2 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 267549af758387..fe9883f2aaf7ff 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -4784,6 +4784,26 @@ "path": "x-pack/plugins/fleet/server/plugin.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-server.FleetSetupDeps.taskManager", + "type": "Object", + "tags": [], + "label": "taskManager", + "description": [], + "signature": [ + { + "pluginId": "taskManager", + "scope": "server", + "docId": "kibTaskManagerPluginApi", + "section": "def-server.TaskManagerSetupContract", + "text": "TaskManagerSetupContract" + } + ], + "path": "x-pack/plugins/fleet/server/plugin.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -5372,14 +5392,8 @@ ", esClient: ", "ElasticsearchClient", ", packagePolicies: ", - { - "pluginId": "fleet", - "scope": "common", - "docId": "kibFleetPluginApi", - "section": "def-common.NewPackagePolicy", - "text": "NewPackagePolicy" - }, - "[], agentPolicyId: string, options?: { user?: ", + "NewPackagePolicyWithId", + "[], options?: { user?: ", { "pluginId": "security", "scope": "common", @@ -5387,7 +5401,7 @@ "section": "def-common.AuthenticatedUser", "text": "AuthenticatedUser" }, - " | undefined; bumpRevision?: boolean | undefined; } | undefined) => Promise<", + " | undefined; bumpRevision?: boolean | undefined; force?: true | undefined; } | undefined) => Promise<", { "pluginId": "fleet", "scope": "common", @@ -5439,13 +5453,7 @@ "label": "packagePolicies", "description": [], "signature": [ - { - "pluginId": "fleet", - "scope": "common", - "docId": "kibFleetPluginApi", - "section": "def-common.NewPackagePolicy", - "text": "NewPackagePolicy" - }, + "NewPackagePolicyWithId", "[]" ], "path": "x-pack/plugins/fleet/server/services/package_policy.ts", @@ -5456,21 +5464,6 @@ { "parentPluginId": "fleet", "id": "def-server.PackagePolicyServiceInterface.bulkCreate.$4", - "type": "string", - "tags": [], - "label": "agentPolicyId", - "description": [], - "signature": [ - "string" - ], - "path": "x-pack/plugins/fleet/server/services/package_policy.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - }, - { - "parentPluginId": "fleet", - "id": "def-server.PackagePolicyServiceInterface.bulkCreate.$5", "type": "Object", "tags": [], "label": "options", @@ -5481,7 +5474,7 @@ "children": [ { "parentPluginId": "fleet", - "id": "def-server.PackagePolicyServiceInterface.bulkCreate.$5.user", + "id": "def-server.PackagePolicyServiceInterface.bulkCreate.$4.user", "type": "Object", "tags": [], "label": "user", @@ -5502,7 +5495,7 @@ }, { "parentPluginId": "fleet", - "id": "def-server.PackagePolicyServiceInterface.bulkCreate.$5.bumpRevision", + "id": "def-server.PackagePolicyServiceInterface.bulkCreate.$4.bumpRevision", "type": "CompoundType", "tags": [], "label": "bumpRevision", @@ -5513,6 +5506,20 @@ "path": "x-pack/plugins/fleet/server/services/package_policy.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackagePolicyServiceInterface.bulkCreate.$4.force", + "type": "boolean", + "tags": [], + "label": "force", + "description": [], + "signature": [ + "true | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/package_policy.ts", + "deprecated": false, + "trackAdoption": false } ] } @@ -6823,7 +6830,9 @@ "section": "def-common.PackageInfo", "text": "PackageInfo" }, - "; }>" + "; experimentalDataStreamFeatures: ", + "ExperimentalDataStreamFeature", + "[]; }>" ], "path": "x-pack/plugins/fleet/server/services/package_policy.ts", "deprecated": false, @@ -10495,6 +10504,20 @@ "path": "x-pack/plugins/fleet/common/types/models/epm.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-common.Installation.experimental_data_stream_features", + "type": "Array", + "tags": [], + "label": "experimental_data_stream_features", + "description": [], + "signature": [ + "{ data_stream: string; features: Record<\"synthetic_source\", boolean>; }[] | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/epm.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -11501,6 +11524,21 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.NewPackagePolicyInputStream.release", + "type": "CompoundType", + "tags": [], + "label": "release", + "description": [], + "signature": [ + "RegistryRelease", + " | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.NewPackagePolicyInputStream.vars", @@ -11901,6 +11939,21 @@ "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-common.PackagePolicyPackage.experimental_data_stream_features", + "type": "Array", + "tags": [], + "label": "experimental_data_stream_features", + "description": [], + "signature": [ + "ExperimentalDataStreamFeature", + "[] | undefined" + ], + "path": "x-pack/plugins/fleet/common/types/models/package_policy.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -12430,10 +12483,13 @@ { "parentPluginId": "fleet", "id": "def-common.RegistryDataStream.RegistryDataStreamKeys.release", - "type": "string", + "type": "CompoundType", "tags": [], "label": "[RegistryDataStreamKeys.release]", "description": [], + "signature": [ + "\"experimental\" | \"beta\" | \"ga\"" + ], "path": "x-pack/plugins/fleet/common/types/models/epm.ts", "deprecated": false, "trackAdoption": false @@ -15255,6 +15311,17 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.AGENT_API_ROUTES.ACTION_STATUS_PATTERN", + "type": "string", + "tags": [], + "label": "ACTION_STATUS_PATTERN", + "description": [], + "path": "x-pack/plugins/fleet/common/constants/routes.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.AGENT_API_ROUTES.LIST_TAGS_PATTERN", @@ -15950,6 +16017,22 @@ "children": [], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-common.agentRouteService.getActionStatusPath", + "type": "Function", + "tags": [], + "label": "getActionStatusPath", + "description": [], + "signature": [ + "() => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-common.agentRouteService.getCurrentUpgradesPath", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index deb8f6162875b1..a7c2c9ba6bb5b4 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Fleet](https://github.com/orgs/elastic/teams/fleet) for questions regar | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 970 | 3 | 873 | 10 | +| 976 | 3 | 879 | 13 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 3318c54d6b6f92..b9698bb6af3ae0 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index ad5da6eb527158..92d86faa822d1e 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index a566a62d1f8467..edccd982c1d6c0 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 5285ccf5319123..be79bdd4eafdbd 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 96c41a5268b4d9..9d0b8a547f1320 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 28ccaee3ae731b..370ea6e08bea10 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index e2601319591a4e..5b08cd3e6a2d5b 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index 1e719609801988..74a80905f75881 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index f55d67c1fc3dc1..8c6373e6be889c 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_utils.mdx b/api_docs/kbn_aiops_utils.mdx index 89439f8a35a2a4..54e66a6a920132 100644 --- a/api_docs/kbn_aiops_utils.mdx +++ b/api_docs/kbn_aiops_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-utils title: "@kbn/aiops-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts.mdx b/api_docs/kbn_alerts.mdx index 132c55a0f53208..58ed7474aecba3 100644 --- a/api_docs/kbn_alerts.mdx +++ b/api_docs/kbn_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts title: "@kbn/alerts" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 023dcb2b4bb369..ddebfb3149f6ea 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index e491c482cb629a..32a1ecee9b0ce0 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index c4ba600af1dab3..878d0e2231d852 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-browser'] --- import kbnAnalyticsShippersElasticV3BrowserObj from './kbn_analytics_shippers_elastic_v3_browser.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx index bb77b10ad5c557..ba54f403fc48f7 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-common'] --- import kbnAnalyticsShippersElasticV3CommonObj from './kbn_analytics_shippers_elastic_v3_common.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx index 1aa6719c6e3135..e9a21b335ee60f 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-elastic-v3-server'] --- import kbnAnalyticsShippersElasticV3ServerObj from './kbn_analytics_shippers_elastic_v3_server.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_fullstory.mdx b/api_docs/kbn_analytics_shippers_fullstory.mdx index 180b6a7699ad30..4afaf927cfd724 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 4b863396dbcf42..909e563b78ea9c 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 01a492a721e05d..ecd3bd9e30bcbe 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 14b01e3c7be4af..48806f0bb59bfa 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index a129e1b408e447..164b274ec16fc5 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index dc390f25f01709..3096620dea8127 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 741443fe91e356..7a21ab47808d9b 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index 40098db9d607fd..3b57ffea662993 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 4d457a94dff83f..07bb1488447532 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index 75ad6cf16351d1..655da00aafaeca 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 988bba727b23c1..f3829af087d231 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index f308239b6d4757..1e7cf2395ca91b 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 0714ab8c48ebf3..a51359f9ea878f 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 1cd0b626f5510a..d5c8ea17e57271 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 7777a057c28945..3cc06db199db25 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index b85fd73d4c9016..9f792a77a0b9aa 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 8937453ad90ef5..6e92b8441660a1 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 21d0c98603bd59..a23c727487684a 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 5bf553a6b4e27e..fa1fbe6a344835 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index 84e37926b9d2ef..a4ac2bbd587e5a 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 08601a43abe024..87a27d7310d32c 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 42e241da77343c..954700546aaeb4 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 5600e432ddde88..918cae2266e65c 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index 36b74b926858bc..740cea27d59aa9 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 53392790ff3213..12a9ea7a3a6927 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index 4596828c8a7f73..2dd30f37d381a1 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 8c56c35df8037b..55cbc90dfb837a 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index e369bc6cf95739..b38af087085f0a 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index a02516d41e635c..d4733df10ef906 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 4cf9fbbbd4890a..107cc07cf99959 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index ed7cb4116ff68c..cdb1bc362db1c3 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index d6275075f4f2d4..aecb098f121234 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 8b8b3352b3e036..26894b359f0990 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index 26b3493760d23c..64f077cc7b79cf 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 6aeec78a9de0b6..f53cd8691aa37e 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index cb3d85753a695b..767eb3ca817be7 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 3f5b097166b70d..e1ccca466b84b1 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index c3308a653104f3..5c7e1685f69db1 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index b77b28d64156f4..14a8dab35c4f56 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index a4c4c5108d54ec..791f954bd0d9eb 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index 6d190e7921922b..b9893dd3939e3c 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index adcb25e4e3b654..0243777cdfa7a5 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index a2fc67402f23ee..8c67ef4c56946e 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index 125a8ddb62eb20..e26596517937da 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 490c09706c8aaa..4e6501e7630e19 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 8507ca2cb39034..b7f0d3997c26bc 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 9aa393700f1cc5..71ed7c7c9f4810 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index 64475b318c5063..d92db48509a8f7 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 3b16e74a4edd20..f3ea30a1089370 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 19bafc1b112daf..ffa295f6afcc94 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 2afd793f95c198..143dfc5595ee96 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 7e71e344bbf24e..4b710a0c95c231 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 36cab5deb51a26..6a0168c3caa86c 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index 1a6af787887d5b..a0256fed88e287 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index ca61b99d2dbab3..8d278f7f7350a2 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 177fc4c26f4ae4..a8d558bdddca7d 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 4200bb38465ccd..e0cf65fe636630 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index b95726bae4f8c2..e31cae82fd5e7a 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 96baa43f4f803f..7389a54ff640a2 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 9d90489b193a27..e7174adca9cc49 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index dc43d1ef8ebe29..547a80c82224f3 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index 72d95cc2173bbb..c561bed47f8e7a 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 2604bdf1307f6e..5aad0c7c3b1568 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index a70c8ebdd20389..d3f87152a47c83 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 090d7dea7fc90c..2cfd6a54f674d8 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 062468ef28b456..f29660dd8fba21 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index 13666c7455aa72..723f7e1143932c 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 8f122bb2f056e3..3ca19cffc1ccd1 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 7bf289e5bff954..3f08c62fb85743 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index d5afd2459cb6a7..cefe2f3a645f9f 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 643fc21c88e998..226665842a30eb 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 337c83d0c71edd..120508a0ac2a53 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 41b228a7827286..5370ae2dcb6ae5 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index 23037163144c57..f51e8e7f1a3f86 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 13949e3052dc57..14f6c84f415b98 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index 35d1ab22608d64..b88acaf3981418 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index 0145a71c0d7b2d..860de97e5d96d6 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser.mdx b/api_docs/kbn_core_injected_metadata_browser.mdx index 87346ec4fa5b72..c954e9385cc366 100644 --- a/api_docs/kbn_core_injected_metadata_browser.mdx +++ b/api_docs/kbn_core_injected_metadata_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser title: "@kbn/core-injected-metadata-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser'] --- import kbnCoreInjectedMetadataBrowserObj from './kbn_core_injected_metadata_browser.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index d9ba50274fda17..9a082a798c071f 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 90e86fc55e65bb..37eda7d25c36fe 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 60f31535742b48..713c2df6ab9fbc 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 302e26129c7121..6a355709ff7dca 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 337f272c28fe55..c7e39b610a15e3 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index 8d4b519f59c142..5ccb082c7f3c1d 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 196c31459d3f23..3731c861c52f91 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index 730e06acc610b0..d3730fb05f6c14 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 11c953906f0dcc..47cfdb2ec87dc7 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index a5ba2bcf8c3cc2..7e01ae47831beb 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 75f3667db69e4b..0a0b87432a4017 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index ace513c8f3fd69..6fcfe6a112b46e 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index ee9a394184d4e5..e96755a7ebb914 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 5333d41e145846..c9f8cc4bcd65cd 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 4a89b92fff036d..aa0acec92d6614 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 14247d429667c7..9c1fffaff6c0ec 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index 0e8f65ff9da071..ef59821d7e6d91 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index 52483dfa4dc6ca..404e9359c8628d 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index 857037bab1093b..c09ca7102eb4d7 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index b2767486e65926..1937ee65cde704 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index 6afb7d61f7327e..4028ed834f0307 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 23ae70cfd0c9f0..5573bad147e849 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 7a3a3d003792fb..32e1362576a19a 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 23db97bef04a91..afb1dc9ea18c97 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index f7574d68fb4aa8..3a804488400036 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index fb970d77d9a9ba..19c4e687936e56 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_internal.mdx b/api_docs/kbn_core_saved_objects_api_server_internal.mdx index 71eb12db08bbce..b1e8550dc02734 100644 --- a/api_docs/kbn_core_saved_objects_api_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-internal title: "@kbn/core-saved-objects-api-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-internal'] --- import kbnCoreSavedObjectsApiServerInternalObj from './kbn_core_saved_objects_api_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index d84f5c5c73c7e4..8f50fcc62296ef 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 93ab71cd6d0c2b..7ab2b50c548aee 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 089cea7cbcd40c..e97f95eff4443c 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index ac8a36714f9c95..3d69cc729ab818 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index afa0e5688428de..a0d8731e24f030 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index fbecff8bedc447..9469f723448ae2 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 56315c20f6063a..e815933ba20516 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index ae5b78204d1b8a..40dcd459d6ed5a 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 0b3f8c2f078bcc..9fe6c428e9c27a 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index e2f35211ba038f..bb9f16fa28ea88 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index c13d91d1c3d3b5..81515bfaabe8cd 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 6e430a5fa2611c..cce8299d8de355 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 06e6a2ecbe2789..2b1b6029e1a0cf 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index f6aecda23d6f1f..92dc8721b5102c 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 5fac3e3216d8af..a310bc5e8b66e3 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 1743916cfc8258..5c4574ce110c4e 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index f815aa153ef383..f9001dab533724 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 30a90ae7a976ab..b055ae6ecd4950 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 1b1bcdac498dd2..9494f0a7234f70 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index d2a4f74edd929c..9df6cb7a9a3c0b 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index 7fecf1916746cb..91fd9f57cde41c 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index 794d64d7e64e92..e5df69dd076bcb 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index f0d5725c883fa5..ff37347c7b544b 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index 65edbdba1a628d..02f3ff216b752c 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index d9f583d515cfcc..9a314c1cbe5c95 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index 925ad46a926100..e041ac38d93f57 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 10165c0389dd68..afc677aa8d2983 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index fed0b546122cdb..f3d3e21b614c56 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 07324152643719..dcb2d58d071cb1 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 5052cc57dc19ef..9168266b9fe5b8 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 79a90a07cb0131..06607ed3de800b 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index 60c5375cd230d2..1bc29e750eebea 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 34d1cab6fdcee2..80a712558dee20 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index cc0de7274d49f8..05d4b7554d8b93 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 59692fd76e3269..0e054dd83877f3 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index b29893225438dc..a595d32b8f67a0 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index a95ffcdf1e28b2..ce61385b75eb4d 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index 5daa6d13cf6a3d..72836a1b1acc8d 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index e76afe4af60ff3..172665b51e32ab 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 0fde4b55f119ed..50c07ff3dbab24 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 2644e4c3b5e711..16c8c03861af52 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index beefe799a31bf0..08efbd7a5dd35c 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 59951f466f8312..33c1c7b9453342 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index cce2805a4412c3..26884ff008b493 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index db4ae2018ca5bf..f35741e1918dcc 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 28ee9c2cff91cf..325ab1ce226565 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 136a0dd3d55f07..5cac179b6f440a 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index eb5455dd7d830a..35d5cdb8041f59 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 40b7ac766e87ac..f2beb74c017989 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_get_repo_files.mdx b/api_docs/kbn_get_repo_files.mdx index 57561b5cbc50f2..35e5ab8d63dd06 100644 --- a/api_docs/kbn_get_repo_files.mdx +++ b/api_docs/kbn_get_repo_files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-get-repo-files title: "@kbn/get-repo-files" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/get-repo-files plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/get-repo-files'] --- import kbnGetRepoFilesObj from './kbn_get_repo_files.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index d2c265790b9b41..1cad16a961c6fd 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 2bf014a652c69a..20aa4591f318d9 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index c2c4c4d0337a88..c4d4b22dbc1cc1 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 4049be82b4dfbd..ca62e86803f782 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 306996d8dcc166..5dbcd32ab606bd 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index e7387cd969effc..2bccca1609123c 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index dbc89d69930c2d..2c4d72e5408a2f 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 943a7e8f6ee378..f418975a89b389 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 42d8da1b6627e2..90afa17190a6d6 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index dca53916d65b63..8eadcf4c53c581 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 6ba7fb075d16d4..6dbc0da558923d 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index 2832f3e8dae4b7..5a7827df403e25 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 9860f169230158..2fa5edd07842bf 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index aff7a4c3270b2e..8c9520301c8dbf 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index a162aa944dc67f..3f2fafd3ccad69 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 875e36a1a99915..b0f261e4b345a2 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 9a84263750a9f5..073f49dc213ccd 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index c7162db39b87cc..47d6bc0a2bf357 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 8b0c2dce899c42..acf9ec1d78dfcd 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index eff3e884b3bd79..deb819dcad4839 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 3fdf23cd53c02e..5f5e071a658e21 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 37bb135d5c2809..5e16c33e604892 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index a5383cbc3b5303..5a70951a8377f4 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index ba7590ffbe159d..2ba6473bb3e119 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 017f82899a8377..949e3675498764 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 49f9e90702310b..0abea591738207 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index ebe0a2779fedf0..22b48a2129619d 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 15d8fcc4196eec..40f2ed946625b5 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index a3eb896fea4c66..dfe673963d5dc6 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index db43ecbf5d1907..c56fabd189f08a 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 3fa0a82da7e870..7818d52f7150e8 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 90ed9b37626b4e..51395791ed9c6d 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index 43dbe59c8b4417..1ce3f1bcd172f8 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index 79e9918ff415aa..e6864509b8e6e4 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 4260459c9d0644..65887938bbe94c 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index d7da0dc87559bd..73a844b9dd2eb4 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 93b46261b29ac2..9b5779b987113d 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 73955118e002c4..3e1d0b8ef67aa9 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index e0d4fb5f40c7da..ade141a8e67ad0 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index ce83347c99d760..281d8e89c4b285 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index aaee03632d3bd2..323cb71fc1ce81 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index 72c05e4c8e5973..a7572422eaaeed 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index 5396d1d529cc3f..06b5847eeb68d7 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx index ebeb4c6b525a95..6a6093117af849 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen-mocks title: "@kbn/shared-ux-button-exit-full-screen-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen-mocks'] --- import kbnSharedUxButtonExitFullScreenMocksObj from './kbn_shared_ux_button_exit_full_screen_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index af5b4f23845c26..9cbd40c50737a1 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index 6fbaa004f2aa15..b6ae546257f68b 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 216b4ec105498a..9a11ebfd2911bd 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index 86b17203dd3aae..802747de697297 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index ba2a281401304a..a93276c45f99d0 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index fc4bed4b1a0013..a50227b43a5667 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index d0c9c5ed9392b5..b804e452681afd 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index f6aa153d98fd14..7bead5768073ff 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 967834391e6dc3..fcb0ade735ac7d 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index 527b5039281e57..8004bc7d98cfdb 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index b132757f0b152a..93f5fa48100571 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index 92be11cf2c6b62..de917d0bf65c26 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 579464a3146de8..13cede26acb542 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index c89f5a58f576e7..bf2f48c4e38bb4 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index f7430ec4cffc92..2de8b2ede36277 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 770abdeea3c3d8..ca958cb334346a 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index f20bc874aa489a..20b052f959e05c 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index c88c99fdfa8e13..eeb46899ad7a5e 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index ad038875cef839..9f235a661078e5 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index 008ba2f53e93cb..376f2050fb0b5c 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index 7883d6366d4f37..1f900664e39bdd 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index c7fe9875c57c67..86aed5cc5727ac 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index bc834ee2ff41a2..e54ef878191ac7 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_package_json.mdx b/api_docs/kbn_sort_package_json.mdx index 1dd32b08c95c52..c95a9ba20dc357 100644 --- a/api_docs/kbn_sort_package_json.mdx +++ b/api_docs/kbn_sort_package_json.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-package-json title: "@kbn/sort-package-json" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-package-json plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-package-json'] --- import kbnSortPackageJsonObj from './kbn_sort_package_json.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index a76ec2f91fad05..030465fcf407e1 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index ffd690fb8d542c..211cac4ef71476 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index 6d4cee2cf48e51..e9d0d67bf11a7a 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index bb0e1cfdac9b08..c0351e06afdc6c 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index bbfa64010e3ba2..97c994093713af 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 762df9d42c29c4..d24ee424962fa1 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 957ed8febfcaee..bfccaa5ccd3b3e 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer.mdx b/api_docs/kbn_type_summarizer.mdx index 98103fbb8df504..be43b6e9eb1eee 100644 --- a/api_docs/kbn_type_summarizer.mdx +++ b/api_docs/kbn_type_summarizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer title: "@kbn/type-summarizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer'] --- import kbnTypeSummarizerObj from './kbn_type_summarizer.devdocs.json'; diff --git a/api_docs/kbn_type_summarizer_core.mdx b/api_docs/kbn_type_summarizer_core.mdx index ff85afae240ef1..066efa8b1567d3 100644 --- a/api_docs/kbn_type_summarizer_core.mdx +++ b/api_docs/kbn_type_summarizer_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-type-summarizer-core title: "@kbn/type-summarizer-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/type-summarizer-core plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/type-summarizer-core'] --- import kbnTypeSummarizerCoreObj from './kbn_type_summarizer_core.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 9e427901caff1a..9c8a14a8d3787d 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 6900408be11c01..5fb427e1a3e3ff 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index cd577edea97f4e..ccf448ad72a099 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index cbe25e33be5094..4b2be39e796aea 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index e2a850694866ba..22ed8a073401ed 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index e09f9577b2b034..6d1b97f05508ee 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index a789dd35533620..9fc13211a68de9 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 8af7864ea49398..1e146c132b1035 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index cb45d6c5a44311..6546152741ab24 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 0de39481f86298..54098ff557a031 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index 1652626d9f56f8..0498b2db5769f7 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.devdocs.json b/api_docs/lens.devdocs.json index 76f715bdb21c98..50822bc6a07feb 100644 --- a/api_docs/lens.devdocs.json +++ b/api_docs/lens.devdocs.json @@ -3594,6 +3594,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "lens", + "id": "def-public.SharedPieLayerState.collapseFns", + "type": "Object", + "tags": [], + "label": "collapseFns", + "description": [], + "signature": [ + "Record<string, string> | undefined" + ], + "path": "x-pack/plugins/lens/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "lens", "id": "def-public.SharedPieLayerState.numberDisplay", @@ -10966,6 +10980,20 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "lens", + "id": "def-common.SharedPieLayerState.collapseFns", + "type": "Object", + "tags": [], + "label": "collapseFns", + "description": [], + "signature": [ + "Record<string, string> | undefined" + ], + "path": "x-pack/plugins/lens/common/types.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "lens", "id": "def-common.SharedPieLayerState.numberDisplay", diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index 6e43b6db2c76be..cb4570fa27620c 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 639 | 0 | 550 | 41 | +| 641 | 0 | 552 | 41 | ## Client diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 48955617613a98..6e309aabace465 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 8c8b8e8c9ef660..9789fa7e0829d0 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 1f36b3105cdc87..2c4102b3e11a95 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index a726ebc34c5fb9..a7fcc3b7e3d0ef 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index 74513f78d1f369..54f3c5582ac843 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index a5fb71bb58e91d..bd17207c428c52 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index 7cac92107a18cb..3c5f70e4b5b686 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 616e1e5a07fc76..d1e758c309a44a 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index afe72ce3daf472..5040b0aced97f3 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index c2674d018305b2..6159a05da37771 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index ac8837b6ca8945..98d97f77364217 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index ba58d7518c6e45..1a117ccbf45c87 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index c580985bc8887d..8694f142fc35c3 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 1e938d796a4a71..f905ec86ea908b 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 40d73b16b018a6..efafbf4a6f6ea7 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 30722 | 180 | 20534 | 971 | +| 30750 | 180 | 20550 | 972 | ## Plugin Directory @@ -48,9 +48,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibDashboardEnhancedPluginApi" text="dashboardEnhanced"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 52 | 0 | 51 | 0 | | <DocLink id="kibDataPluginApi" text="data"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3144 | 34 | 2444 | 23 | | <DocLink id="kibDataViewEditorPluginApi" text="dataViewEditor"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create data views via a modal flyout inside Kibana apps | 15 | 0 | 7 | 0 | -| <DocLink id="kibDataViewFieldEditorPluginApi" text="dataViewFieldEditor"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 49 | 0 | 29 | 3 | +| <DocLink id="kibDataViewFieldEditorPluginApi" text="dataViewFieldEditor"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Reusable data view field editor across Kibana | 60 | 0 | 30 | 0 | | <DocLink id="kibDataViewManagementPluginApi" text="dataViewManagement"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data view management app | 2 | 0 | 2 | 0 | -| <DocLink id="kibDataViewsPluginApi" text="dataViews"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 963 | 0 | 206 | 1 | +| <DocLink id="kibDataViewsPluginApi" text="dataViews"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 966 | 0 | 208 | 1 | | <DocLink id="kibDataVisualizerPluginApi" text="dataVisualizer"/> | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 28 | 3 | 24 | 1 | | <DocLink id="kibDevToolsPluginApi" text="devTools"/> | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 10 | 0 | 8 | 2 | | <DocLink id="kibDiscoverPluginApi" text="discover"/> | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 95 | 0 | 78 | 4 | @@ -80,7 +80,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibFieldFormatsPluginApi" text="fieldFormats"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 5 | 249 | 3 | | <DocLink id="kibFileUploadPluginApi" text="fileUpload"/> | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 62 | 0 | 62 | 2 | | <DocLink id="kibFilesPluginApi" text="files"/> | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/team:AppServicesUx) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 240 | 0 | 6 | 2 | -| <DocLink id="kibFleetPluginApi" text="fleet"/> | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 970 | 3 | 873 | 10 | +| <DocLink id="kibFleetPluginApi" text="fleet"/> | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 976 | 3 | 879 | 13 | | <DocLink id="kibGlobalSearchPluginApi" text="globalSearch"/> | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -99,7 +99,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | kibanaUsageCollection | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 0 | 0 | 0 | 0 | | <DocLink id="kibKibanaUtilsPluginApi" text="kibanaUtils"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 615 | 3 | 418 | 9 | | <DocLink id="kibKubernetesSecurityPluginApi" text="kubernetesSecurity"/> | [Security Team](https://github.com/orgs/elastic/teams/security-team) | - | 3 | 0 | 3 | 1 | -| <DocLink id="kibLensPluginApi" text="lens"/> | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 639 | 0 | 550 | 41 | +| <DocLink id="kibLensPluginApi" text="lens"/> | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 641 | 0 | 552 | 41 | | <DocLink id="kibLicenseApiGuardPluginApi" text="licenseApiGuard"/> | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | | <DocLink id="kibLicenseManagementPluginApi" text="licenseManagement"/> | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 3 | 0 | 3 | 0 | | <DocLink id="kibLicensingPluginApi" text="licensing"/> | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 10 | @@ -120,7 +120,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibRemoteClustersPluginApi" text="remoteClusters"/> | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 4 | 0 | 4 | 0 | | <DocLink id="kibReportingPluginApi" text="reporting"/> | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 36 | 0 | 16 | 0 | | <DocLink id="kibRollupPluginApi" text="rollup"/> | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 21 | 0 | 21 | 0 | -| <DocLink id="kibRuleRegistryPluginApi" text="ruleRegistry"/> | [RAC](https://github.com/orgs/elastic/teams/rac) | - | 208 | 0 | 180 | 10 | +| <DocLink id="kibRuleRegistryPluginApi" text="ruleRegistry"/> | [RAC](https://github.com/orgs/elastic/teams/rac) | - | 213 | 0 | 185 | 11 | | <DocLink id="kibRuntimeFieldsPluginApi" text="runtimeFields"/> | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 24 | 0 | 19 | 2 | | <DocLink id="kibSavedObjectsPluginApi" text="savedObjects"/> | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 193 | 2 | 152 | 5 | | <DocLink id="kibSavedObjectsFinderPluginApi" text="savedObjectsFinder"/> | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 16 | 0 | 16 | 0 | @@ -139,7 +139,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibSpacesPluginApi" text="spaces"/> | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides the Spaces feature, which allows saved objects to be organized into meaningful categories. | 260 | 0 | 64 | 0 | | <DocLink id="kibStackAlertsPluginApi" text="stackAlerts"/> | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 4 | 0 | 4 | 0 | | synthetics | [Uptime](https://github.com/orgs/elastic/teams/uptime) | This plugin visualizes data from Synthetics and Heartbeat, and integrates with other Observability solutions. | 0 | 0 | 0 | 0 | -| <DocLink id="kibTaskManagerPluginApi" text="taskManager"/> | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 82 | 0 | 41 | 7 | +| <DocLink id="kibTaskManagerPluginApi" text="taskManager"/> | [Response Ops](https://github.com/orgs/elastic/teams/response-ops) | - | 83 | 0 | 41 | 7 | | <DocLink id="kibTelemetryPluginApi" text="telemetry"/> | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 44 | 0 | 1 | 0 | | <DocLink id="kibTelemetryCollectionManagerPluginApi" text="telemetryCollectionManager"/> | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 31 | 0 | 26 | 6 | | <DocLink id="kibTelemetryCollectionXpackPluginApi" text="telemetryCollectionXpack"/> | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 1 | 0 | 1 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index ecf895a3e0f7a0..0edc689af574fd 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 9d61b29944ba92..78ddad2eb86f28 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index 286139d6fe63f3..6f458120aba1b7 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index 3a26281e749b68..dd24570ed202c4 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.devdocs.json b/api_docs/rule_registry.devdocs.json index dff8ff4faf897a..63cb7763de4a9d 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -401,6 +401,77 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-server.AlertsClient.getBrowserFields", + "type": "Function", + "tags": [], + "label": "getBrowserFields", + "description": [], + "signature": [ + "({ indices, metaFields, allowNoIndex, }: { indices: string[]; metaFields: string[]; allowNoIndex: boolean; }) => Promise<", + "BrowserFields", + ">" + ], + "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "ruleRegistry", + "id": "def-server.AlertsClient.getBrowserFields.$1", + "type": "Object", + "tags": [], + "label": "{\n indices,\n metaFields,\n allowNoIndex,\n }", + "description": [], + "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "ruleRegistry", + "id": "def-server.AlertsClient.getBrowserFields.$1.indices", + "type": "Array", + "tags": [], + "label": "indices", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-server.AlertsClient.getBrowserFields.$1.metaFields", + "type": "Array", + "tags": [], + "label": "metaFields", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "ruleRegistry", + "id": "def-server.AlertsClient.getBrowserFields.$1.allowNoIndex", + "type": "boolean", + "tags": [], + "label": "allowNoIndex", + "description": [], + "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index c9236042b14f04..5f6fc879c4139a 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; @@ -21,7 +21,7 @@ Contact [RAC](https://github.com/orgs/elastic/teams/rac) for questions regarding | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 208 | 0 | 180 | 10 | +| 213 | 0 | 185 | 11 | ## Server diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index d04909af548968..171c76855d8e0d 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 03f4861574ec82..78f2c22a48ff32 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 312293e55cc627..2da7af5edaa258 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index e629a877e6a51a..7e987845a7f6e4 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 456808d926a824..5d518c6f38be80 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 8dc7f9e54649e1..11d80f83e37bed 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 15f259f2794d48..d64af3ea0899f8 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index 5c308f8c268e95..69b385c778d533 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 47f80ea4bfb327..b55f6e9cab5410 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index e1d55dd7b8f5e7..ee218b50a477e2 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 29a07610f1e5c5..e1fd0a2477294d 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 9c8e4190bf491c..f4305bd1a9f45a 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index 6bd52414173b99..fdb2d1e61b2f81 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 1e59aff6842ba3..4770ea6d27907b 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 02b72e1835c090..933ca6900c3b6d 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 85ade27d7ba7e5..186450bead6663 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/task_manager.devdocs.json b/api_docs/task_manager.devdocs.json index 98ff17ac35f74b..0a6584f16c6daf 100644 --- a/api_docs/task_manager.devdocs.json +++ b/api_docs/task_manager.devdocs.json @@ -429,10 +429,10 @@ "interfaces": [ { "parentPluginId": "taskManager", - "id": "def-server.BulkUpdateSchedulesResult", + "id": "def-server.BulkUpdateTaskResult", "type": "Interface", "tags": [], - "label": "BulkUpdateSchedulesResult", + "label": "BulkUpdateTaskResult", "description": [ "\nreturn type of TaskScheduling.bulkUpdateSchedules method" ], @@ -442,7 +442,7 @@ "children": [ { "parentPluginId": "taskManager", - "id": "def-server.BulkUpdateSchedulesResult.tasks", + "id": "def-server.BulkUpdateTaskResult.tasks", "type": "Array", "tags": [], "label": "tasks", @@ -465,7 +465,7 @@ }, { "parentPluginId": "taskManager", - "id": "def-server.BulkUpdateSchedulesResult.errors", + "id": "def-server.BulkUpdateTaskResult.errors", "type": "Array", "tags": [], "label": "errors", @@ -993,6 +993,22 @@ "path": "x-pack/plugins/task_manager/server/task.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "taskManager", + "id": "def-server.TaskInstance.enabled", + "type": "CompoundType", + "tags": [], + "label": "enabled", + "description": [ + "\nIndicates whether the task is currently enabled. Disabled tasks will not be claimed." + ], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/plugins/task_manager/server/task.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1216,7 +1232,7 @@ "\nA task instance that has an id and is ready for storage." ], "signature": [ - "{ params: Record<string, any>; state: Record<string, any>; scope?: string[] | undefined; taskType: string; }" + "{ params: Record<string, any>; enabled?: boolean | undefined; state: Record<string, any>; scope?: string[] | undefined; taskType: string; }" ], "path": "x-pack/plugins/task_manager/server/task.ts", "deprecated": false, @@ -1516,7 +1532,7 @@ "signature": [ "Pick<", "TaskScheduling", - ", \"schedule\" | \"runSoon\" | \"ephemeralRunNow\" | \"ensureScheduled\" | \"bulkUpdateSchedules\" | \"bulkSchedule\"> & Pick<", + ", \"schedule\" | \"runSoon\" | \"ephemeralRunNow\" | \"ensureScheduled\" | \"bulkUpdateSchedules\" | \"bulkEnableDisable\" | \"bulkSchedule\"> & Pick<", "TaskStore", ", \"get\" | \"aggregate\" | \"fetch\" | \"remove\"> & { removeIfExists: (id: string) => Promise<void>; } & { supportsEphemeralTasks: () => boolean; }" ], diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 696dc5d8713357..b792174229db5e 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; @@ -21,7 +21,7 @@ Contact [Response Ops](https://github.com/orgs/elastic/teams/response-ops) for q | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 82 | 0 | 41 | 7 | +| 83 | 0 | 41 | 7 | ## Server diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 3a62678f11769d..7f949fecc09fda 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 30f763ba4488f5..43bcac0fd2464e 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index f56b57fe0398c4..12a60401eeebe7 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 80abde5c72bc85..32e5ab2f192cde 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 8e620fcd483210..b61378c50bbaae 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 020d59da436aa6..3f3b87205d761c 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 27facd7cbc7910..208db579bbef08 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 6b6af45f6d599c..855cd38f3c4c1a 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 68f0239219c7a6..35e4aeabada7f2 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index f9e3c5956fea5c..d7e183c85606d5 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_field_list.mdx b/api_docs/unified_field_list.mdx index 82043a2029661c..acc4fe78bbe537 100644 --- a/api_docs/unified_field_list.mdx +++ b/api_docs/unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedFieldList title: "unifiedFieldList" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedFieldList plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 5b3a5638c74ef1..5aec9e4ea7ca7e 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index bebe8e757136a4..acb7f297ddeb1b 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index ba4d70200d7143..ee0673e504768e 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index eac1395483f264..a7e7d8c6ae0b67 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index ac07b7b6dec90d..2bfeb944d13cba 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 27386a94c37aa3..9887aca5925cee 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index c25eb47e0fbdc8..61fcc96d1788ce 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 492e3f940e9909..8bdd2af90b27bc 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index bd06921b3a7404..93f00ba7ce5bd3 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index 32a53d10810cc3..00a263cb6047c9 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index 1a0fe74391504c..c5b69594c76e3f 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index faaeaad6e7c4b7..181e21f0ae85a8 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 9892ae39456836..d34eeb693643ab 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index d2862d4828d210..e68edfdc210294 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 8c22d419a997cf..907fb00eb00545 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index eb856d91fcbba0..bbe7f2164107a7 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2022-09-12 +date: 2022-09-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 191bfbc97ef90a18469bcc4a5cd53e706388d36c Mon Sep 17 00:00:00 2001 From: Rudolf Meijering <skaapgif@gmail.com> Date: Tue, 13 Sep 2022 09:56:29 +0200 Subject: [PATCH 092/144] Saved objects: improve typesafety (#140099) * Remove SavedObjectAttributes from examples * Remove SavedObjectAttributes from dev_docs * Deprecate SavedObjectAttributes type * Remove SavedObjectAttributes from kibana_usage_collection plugin * Remove low hanging SavedObjectAttributes in security_solution * Remove low hanging SavedObjectAttributes in upgrade_assistant * Remove low hanging SavedObjectAttributes in lens * Stricter types for SavedObjectsServiceSetup.registerType * Review feedback * Some more low hanging fruit Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- dev_docs/tutorials/testing_plugins.mdx | 3 +-- .../common/book_saved_object_attributes.ts | 5 +---- .../common/todo_saved_object_attributes.ts | 4 +--- .../src/apis/bulk_update.ts | 2 +- .../core-saved-objects-common/src/saved_objects.ts | 3 ++- .../core-saved-objects-server/src/contracts.ts | 5 +---- .../default_embeddable_factory_provider.ts | 2 +- .../public/lib/embeddables/embeddable_factory.ts | 3 +-- .../lib/embeddables/embeddable_factory_definition.ts | 3 +-- src/plugins/embeddable/public/types.ts | 2 +- .../application_usage/saved_objects_types.ts | 4 ++-- .../collectors/event_loop_delays/saved_objects.ts | 8 ++------ .../ui_metric/telemetry_ui_metric_collector.ts | 8 ++------ .../server/usage_counters/saved_objects.ts | 3 +-- .../saved_object_export_transforms/server/plugin.ts | 12 ++++++------ .../saved_object_import_warnings/server/plugin.ts | 4 ++-- x-pack/plugins/actions/server/actions_client.ts | 2 +- x-pack/plugins/embeddable_enhanced/public/plugin.ts | 3 +-- .../lens/public/persistence/saved_object_store.ts | 5 +---- .../saved_objects_utils/find_object_by_title.ts | 8 ++------ .../maps/server/saved_objects/setup_saved_objects.ts | 2 +- .../detection_engine/rules/get_prepackaged_rules.ts | 3 +-- .../server/lib/detection_engine/rules/types.ts | 4 ++-- .../lib/timeline/saved_object/notes/saved_object.ts | 10 +--------- .../lib/timeline/saved_object/pinned_events/index.ts | 10 +--------- .../synthetics_service/hydrate_saved_object.ts | 4 +++- x-pack/plugins/upgrade_assistant/common/types.ts | 10 +++++----- .../fixtures/spaces_test_plugin/server/plugin.ts | 4 ++-- 28 files changed, 47 insertions(+), 89 deletions(-) diff --git a/dev_docs/tutorials/testing_plugins.mdx b/dev_docs/tutorials/testing_plugins.mdx index 4fbfd1b2574437..84e43310e46c8a 100644 --- a/dev_docs/tutorials/testing_plugins.mdx +++ b/dev_docs/tutorials/testing_plugins.mdx @@ -688,11 +688,10 @@ reflected in the mock. // src/plugins/myplugin/public/saved_query_service.ts import { SavedObjectsClientContract, - SavedObjectAttributes, SimpleSavedObject, } from 'src/core/public'; -export type SavedQueryAttributes = SavedObjectAttributes & { +export type SavedQueryAttributes = { title: string; description: 'bar'; query: { diff --git a/examples/embeddable_examples/common/book_saved_object_attributes.ts b/examples/embeddable_examples/common/book_saved_object_attributes.ts index 0ab84e42e3d9f3..bf1073486fcfb0 100644 --- a/examples/embeddable_examples/common/book_saved_object_attributes.ts +++ b/examples/embeddable_examples/common/book_saved_object_attributes.ts @@ -5,12 +5,9 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import type { SavedObjectAttributes } from '@kbn/core/types'; - export const BOOK_SAVED_OBJECT = 'book'; -export interface BookSavedObjectAttributes extends SavedObjectAttributes { +export interface BookSavedObjectAttributes { title: string; author?: string; readIt?: boolean; diff --git a/examples/embeddable_examples/common/todo_saved_object_attributes.ts b/examples/embeddable_examples/common/todo_saved_object_attributes.ts index 21994add4ed42d..e165522e88590d 100644 --- a/examples/embeddable_examples/common/todo_saved_object_attributes.ts +++ b/examples/embeddable_examples/common/todo_saved_object_attributes.ts @@ -6,9 +6,7 @@ * Side Public License, v 1. */ -import type { SavedObjectAttributes } from '@kbn/core/types'; - -export interface TodoSavedObjectAttributes extends SavedObjectAttributes { +export interface TodoSavedObjectAttributes { task: string; icon?: string; title?: string; diff --git a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_update.ts b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_update.ts index 102e46809b55e6..858504853dd754 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_update.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server/src/apis/bulk_update.ts @@ -19,7 +19,7 @@ export interface SavedObjectsBulkUpdateObject<T = unknown> id: string; /** The type of this Saved Object. Each plugin can define it's own custom Saved Object types. */ type: string; - /** {@inheritdoc SavedObjectAttributes} */ + /** The data for a Saved Object is stored as an object in the `attributes` property. **/ attributes: Partial<T>; /** * Optional namespace string to use when searching for this object. If this is defined, it will supersede the namespace ID that is in diff --git a/packages/core/saved-objects/core-saved-objects-common/src/saved_objects.ts b/packages/core/saved-objects/core-saved-objects-common/src/saved_objects.ts index 2b8f6d66e67ac7..b9bdbafc213c93 100644 --- a/packages/core/saved-objects/core-saved-objects-common/src/saved_objects.ts +++ b/packages/core/saved-objects/core-saved-objects-common/src/saved_objects.ts @@ -31,6 +31,7 @@ export type SavedObjectAttribute = SavedObjectAttributeSingle | SavedObjectAttri * property. * * @public + * @deprecated This type reduces the type safety of your code. Create an interface for your specific saved object type or use `unknown` instead. */ export interface SavedObjectAttributes { [key: string]: SavedObjectAttribute; @@ -76,7 +77,7 @@ export interface SavedObject<T = unknown> { /** Timestamp of the last time this document had been updated. */ updated_at?: string; error?: SavedObjectError; - /** {@inheritdoc SavedObjectAttributes} */ + /** The data for a Saved Object is stored as an object in the `attributes` property. **/ attributes: T; /** {@inheritdoc SavedObjectReference} */ references: SavedObjectReference[]; diff --git a/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts b/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts index bb790aec293c82..20821cef46e7a1 100644 --- a/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts +++ b/packages/core/saved-objects/core-saved-objects-server/src/contracts.ts @@ -7,7 +7,6 @@ */ import type { KibanaRequest } from '@kbn/core-http-server'; -import type { SavedObjectAttributes } from '@kbn/core-saved-objects-common'; import type { SavedObjectsClientContract, ISavedObjectsRepository, @@ -124,9 +123,7 @@ export interface SavedObjectsServiceSetup { * } * ``` */ - registerType: <Attributes extends SavedObjectAttributes = any>( - type: SavedObjectsType<Attributes> - ) => void; + registerType: <Attributes = unknown>(type: SavedObjectsType<Attributes>) => void; /** * Returns the default index used for saved objects. diff --git a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts index 17103bc8783ffa..e7b8893848c930 100644 --- a/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts +++ b/src/plugins/embeddable/public/lib/embeddables/default_embeddable_factory_provider.ts @@ -17,7 +17,7 @@ export const defaultEmbeddableFactoryProvider = < I extends EmbeddableInput = EmbeddableInput, O extends EmbeddableOutput = EmbeddableOutput, E extends IEmbeddable<I, O> = IEmbeddable<I, O>, - T extends SavedObjectAttributes = SavedObjectAttributes + T = SavedObjectAttributes >( def: EmbeddableFactoryDefinition<I, O, E, T> ): EmbeddableFactory<I, O, E, T> => { diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts index e1b7a48948743e..317ff4f773f232 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { SavedObjectAttributes } from '@kbn/core/public'; import { SavedObjectMetaData } from '@kbn/saved-objects-plugin/public'; import { PersistableState } from '@kbn/kibana-utils-plugin/common'; import { UiActionsPresentableGrouping } from '@kbn/ui-actions-plugin/public'; @@ -35,7 +34,7 @@ export interface EmbeddableFactory< TEmbeddableInput, TEmbeddableOutput >, - TSavedObjectAttributes extends SavedObjectAttributes = SavedObjectAttributes + TSavedObjectAttributes = unknown > extends PersistableState<EmbeddableStateWithType> { // A unique identified for this factory, which will be used to map an embeddable spec to // a factory that can generate an instance of it. diff --git a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts index 2ae5d4161e15dc..06f3a268c9ae5f 100644 --- a/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts +++ b/src/plugins/embeddable/public/lib/embeddables/embeddable_factory_definition.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import type { SavedObjectAttributes } from '@kbn/core/server'; import { IEmbeddable } from './i_embeddable'; import { EmbeddableFactory } from './embeddable_factory'; import { EmbeddableInput, EmbeddableOutput } from '..'; @@ -15,7 +14,7 @@ export type EmbeddableFactoryDefinition< I extends EmbeddableInput = EmbeddableInput, O extends EmbeddableOutput = EmbeddableOutput, E extends IEmbeddable<I, O> = IEmbeddable<I, O>, - T extends SavedObjectAttributes = SavedObjectAttributes + T = unknown > = // Required parameters Pick<EmbeddableFactory<I, O, E, T>, 'create' | 'type' | 'isEditable' | 'getDisplayName'> & diff --git a/src/plugins/embeddable/public/types.ts b/src/plugins/embeddable/public/types.ts index 29f38c2f1916bc..7f24f525ae49f2 100644 --- a/src/plugins/embeddable/public/types.ts +++ b/src/plugins/embeddable/public/types.ts @@ -34,7 +34,7 @@ export type EmbeddableFactoryProvider = < I extends EmbeddableInput = EmbeddableInput, O extends EmbeddableOutput = EmbeddableOutput, E extends IEmbeddable<I, O> = IEmbeddable<I, O>, - T extends SavedObjectAttributes = SavedObjectAttributes + T = SavedObjectAttributes >( def: EmbeddableFactoryDefinition<I, O, E, T> ) => EmbeddableFactory<I, O, E, T>; diff --git a/src/plugins/kibana_usage_collection/server/collectors/application_usage/saved_objects_types.ts b/src/plugins/kibana_usage_collection/server/collectors/application_usage/saved_objects_types.ts index fdf6e99f7280de..ba767658e84919 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/application_usage/saved_objects_types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/application_usage/saved_objects_types.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ -import type { SavedObjectAttributes, SavedObjectsServiceSetup } from '@kbn/core/server'; +import type { SavedObjectsServiceSetup } from '@kbn/core/server'; /** * Used for accumulating the totals of all the stats older than 90d */ -export interface ApplicationUsageTotal extends SavedObjectAttributes { +export interface ApplicationUsageTotal { appId: string; viewId: string; minutesOnScreen: number; diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts index cf0c5372450e50..a980e0257e7e27 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/saved_objects.ts @@ -6,16 +6,12 @@ * Side Public License, v 1. */ -import type { - SavedObjectAttributes, - SavedObjectsServiceSetup, - ISavedObjectsRepository, -} from '@kbn/core/server'; +import type { SavedObjectsServiceSetup, ISavedObjectsRepository } from '@kbn/core/server'; import moment from 'moment'; import type { IntervalHistogram } from '@kbn/core/server'; export const SAVED_OBJECTS_DAILY_TYPE = 'event_loop_delays_daily'; -export interface EventLoopDelaysDaily extends SavedObjectAttributes, IntervalHistogram { +export interface EventLoopDelaysDaily extends IntervalHistogram { processId: number; instanceUuid: string; } diff --git a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts index 833e537b92ddfb..917d7a06a0f473 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/ui_metric/telemetry_ui_metric_collector.ts @@ -6,15 +6,11 @@ * Side Public License, v 1. */ -import { - ISavedObjectsRepository, - SavedObjectAttributes, - SavedObjectsServiceSetup, -} from '@kbn/core/server'; +import { ISavedObjectsRepository, SavedObjectsServiceSetup } from '@kbn/core/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { uiMetricSchema } from './schema'; -interface UIMetricsSavedObjects extends SavedObjectAttributes { +interface UIMetricsSavedObjects { count: number; } diff --git a/src/plugins/usage_collection/server/usage_counters/saved_objects.ts b/src/plugins/usage_collection/server/usage_counters/saved_objects.ts index 2752696f24711f..701bbba404c497 100644 --- a/src/plugins/usage_collection/server/usage_counters/saved_objects.ts +++ b/src/plugins/usage_collection/server/usage_counters/saved_objects.ts @@ -9,7 +9,6 @@ import type { SavedObject, SavedObjectsRepository, - SavedObjectAttributes, SavedObjectsServiceSetup, } from '@kbn/core/server'; import moment from 'moment'; @@ -18,7 +17,7 @@ import type { CounterMetric } from './usage_counter'; /** * The attributes stored in the UsageCounters' SavedObjects */ -export interface UsageCountersSavedObjectAttributes extends SavedObjectAttributes { +export interface UsageCountersSavedObjectAttributes { /** The domain ID registered in the Usage Counter **/ domainId: string; /** The counter name **/ diff --git a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts index ce8119cfd0acc9..4c3abebc8143f1 100644 --- a/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts +++ b/test/plugin_functional/plugins/saved_object_export_transforms/server/plugin.ts @@ -16,7 +16,7 @@ export class SavedObjectExportTransformsPlugin implements Plugin { // example of a SO type that will mutates its properties // during the export transform - savedObjects.registerType({ + savedObjects.registerType<{ title: string; enabled: boolean }>({ name: 'test-export-transform', hidden: false, namespaceType: 'single', @@ -46,7 +46,7 @@ export class SavedObjectExportTransformsPlugin implements Plugin { // example of a SO type that will add additional objects // to the export during the export transform - savedObjects.registerType({ + savedObjects.registerType<{ title: string }>({ name: 'test-export-add', hidden: false, namespaceType: 'single', @@ -74,7 +74,7 @@ export class SavedObjectExportTransformsPlugin implements Plugin { // dependency of `test_export_transform_2` that will be included // when exporting them - savedObjects.registerType({ + savedObjects.registerType<{ title: string }>({ name: 'test-export-add-dep', hidden: false, namespaceType: 'single', @@ -91,7 +91,7 @@ export class SavedObjectExportTransformsPlugin implements Plugin { }); // example of a SO type that will throw an object-transform-error - savedObjects.registerType({ + savedObjects.registerType<{ title: string }>({ name: 'test-export-transform-error', hidden: false, namespaceType: 'single', @@ -111,7 +111,7 @@ export class SavedObjectExportTransformsPlugin implements Plugin { }); // example of a SO type that will throw an invalid-transform-error - savedObjects.registerType({ + savedObjects.registerType<{ title: string }>({ name: 'test-export-invalid-transform', hidden: false, namespaceType: 'single', @@ -134,7 +134,7 @@ export class SavedObjectExportTransformsPlugin implements Plugin { }); // example of a SO type that is exportable while being hidden - savedObjects.registerType({ + savedObjects.registerType<{ title: string; enabled: boolean }>({ name: 'test-actions-export-hidden', hidden: true, namespaceType: 'single', diff --git a/test/plugin_functional/plugins/saved_object_import_warnings/server/plugin.ts b/test/plugin_functional/plugins/saved_object_import_warnings/server/plugin.ts index 364f094ccf7cb1..f2d99539df19fd 100644 --- a/test/plugin_functional/plugins/saved_object_import_warnings/server/plugin.ts +++ b/test/plugin_functional/plugins/saved_object_import_warnings/server/plugin.ts @@ -10,7 +10,7 @@ import { Plugin, CoreSetup } from '@kbn/core/server'; export class SavedObjectImportWarningsPlugin implements Plugin { public setup({ savedObjects }: CoreSetup, deps: {}) { - savedObjects.registerType({ + savedObjects.registerType<{ title: string }>({ name: 'test_import_warning_1', hidden: false, namespaceType: 'single', @@ -31,7 +31,7 @@ export class SavedObjectImportWarningsPlugin implements Plugin { }, }); - savedObjects.registerType({ + savedObjects.registerType<{ title: string }>({ name: 'test_import_warning_2', hidden: false, namespaceType: 'single', diff --git a/x-pack/plugins/actions/server/actions_client.ts b/x-pack/plugins/actions/server/actions_client.ts index d2777a8e3ae68c..73d5b32d077a98 100644 --- a/x-pack/plugins/actions/server/actions_client.ts +++ b/x-pack/plugins/actions/server/actions_client.ts @@ -78,7 +78,7 @@ import { // We'll set this max setting assuming it's never reached. export const MAX_ACTIONS_RETURNED = 10000; -interface ActionUpdate extends SavedObjectAttributes { +interface ActionUpdate { name: string; config: SavedObjectAttributes; secrets: SavedObjectAttributes; diff --git a/x-pack/plugins/embeddable_enhanced/public/plugin.ts b/x-pack/plugins/embeddable_enhanced/public/plugin.ts index 61958c114c632c..ed829a9326e9e3 100644 --- a/x-pack/plugins/embeddable_enhanced/public/plugin.ts +++ b/x-pack/plugins/embeddable_enhanced/public/plugin.ts @@ -6,7 +6,6 @@ */ import { CoreStart, CoreSetup, Plugin, PluginInitializerContext } from '@kbn/core/public'; -import { SavedObjectAttributes } from '@kbn/core/public'; import { EmbeddableFactory, EmbeddableFactoryDefinition, @@ -77,7 +76,7 @@ export class EmbeddableEnhancedPlugin I extends EmbeddableInput = EmbeddableInput, O extends EmbeddableOutput = EmbeddableOutput, E extends IEmbeddable<I, O> = IEmbeddable<I, O>, - T extends SavedObjectAttributes = SavedObjectAttributes + T = unknown >( def: EmbeddableFactoryDefinition<I, O, E, T> ): EmbeddableFactory<I, O, E, T> => { diff --git a/x-pack/plugins/lens/public/persistence/saved_object_store.ts b/x-pack/plugins/lens/public/persistence/saved_object_store.ts index a059be6db3bfab..4ee70b9480d173 100644 --- a/x-pack/plugins/lens/public/persistence/saved_object_store.ts +++ b/x-pack/plugins/lens/public/persistence/saved_object_store.ts @@ -7,7 +7,6 @@ import { Filter, Query } from '@kbn/es-query'; import { - SavedObjectAttributes, SavedObjectsClientContract, SavedObjectReference, ResolvedSimpleSavedObject, @@ -56,9 +55,7 @@ export class SavedObjectIndexStore implements SavedObjectStore { save = async (vis: Document) => { const { savedObjectId, type, references, ...rest } = vis; - // TODO: SavedObjectAttributes should support this kind of object, - // remove this workaround when SavedObjectAttributes is updated. - const attributes = rest as unknown as SavedObjectAttributes; + const attributes = rest; const result = await this.client.create( DOC_TYPE, diff --git a/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.ts b/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.ts index b556f960d6e242..1fda36f4ada364 100644 --- a/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.ts +++ b/x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.ts @@ -5,14 +5,10 @@ * 2.0. */ -import type { - SavedObjectsClientContract, - SimpleSavedObject, - SavedObjectAttributes, -} from '@kbn/core/public'; +import type { SavedObjectsClientContract, SimpleSavedObject } from '@kbn/core/public'; /** Returns an object matching a given title */ -export async function findObjectByTitle<T extends SavedObjectAttributes>( +export async function findObjectByTitle<T>( savedObjectsClient: SavedObjectsClientContract, type: string, title: string diff --git a/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts b/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts index 7bc209b4b1a9fb..caa99d98662c15 100644 --- a/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts +++ b/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts @@ -19,7 +19,7 @@ export function setupSavedObjects( core: CoreSetup, getFilterMigrations: () => MigrateFunctionsObject ) { - core.savedObjects.registerType({ + core.savedObjects.registerType<MapSavedObjectAttributes>({ name: 'map', hidden: false, namespaceType: 'multiple-isolated', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_prepackaged_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_prepackaged_rules.ts index 38d287754fa953..f01f6820b2687f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_prepackaged_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_prepackaged_rules.ts @@ -5,7 +5,6 @@ * 2.0. */ -import type { SavedObjectAttributes } from '@kbn/core/types'; import { BadRequestError } from '@kbn/securitysolution-es-utils'; import { exactCheck, formatErrors } from '@kbn/securitysolution-io-ts-utils'; import { fold } from 'fp-ts/lib/Either'; @@ -56,7 +55,7 @@ export const validateAllPrepackagedRules = ( * Validate the rules from Saved Objects created by Fleet. */ export const validateAllRuleSavedObjects = ( - rules: Array<IRuleAssetSOAttributes & SavedObjectAttributes> + rules: IRuleAssetSOAttributes[] ): AddPrepackagedRulesSchema[] => { return rules.map((rule) => { const decoded = addPrepackagedRulesSchema.decode(rule); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts index e02daa7c88c40c..e1b55ca9124b1b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/types.ts @@ -7,7 +7,7 @@ import type { Readable } from 'stream'; -import type { SavedObjectAttributes, SavedObjectsClientContract } from '@kbn/core/server'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { SanitizedRule } from '@kbn/alerting-plugin/common'; import type { RulesClient, PartialRule } from '@kbn/alerting-plugin/server'; import { ruleTypeMappings } from '@kbn/securitysolution-rules'; @@ -43,7 +43,7 @@ export interface IRuleAssetSOAttributes extends Record<string, any> { export interface IRuleAssetSavedObject { type: string; id: string; - attributes: IRuleAssetSOAttributes & SavedObjectAttributes; + attributes: IRuleAssetSOAttributes; } export interface HapiReadableStream extends Readable { diff --git a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/notes/saved_object.ts b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/notes/saved_object.ts index 34280fac17e5e5..bc012953fa0d14 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/notes/saved_object.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/notes/saved_object.ts @@ -258,19 +258,11 @@ export const convertSavedObjectToSavedNote = ( }, identity) ); -// we have to use any here because the SavedObjectAttributes interface is like below -// export interface SavedObjectAttributes { -// [key: string]: SavedObjectAttributes | string | number | boolean | null; -// } -// then this interface does not allow types without index signature -// this is limiting us with our type for now so the easy way was to use any - const pickSavedNote = ( noteId: string | null, savedNote: SavedNote, userInfo: AuthenticatedUser | null - // eslint-disable-next-line @typescript-eslint/no-explicit-any -): any => { +) => { if (noteId == null) { savedNote.created = new Date().valueOf(); savedNote.createdBy = userInfo?.username ?? UNAUTHENTICATED_USER; diff --git a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/pinned_events/index.ts b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/pinned_events/index.ts index ff6fd55bd58929..c6c5f216174ce6 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/saved_object/pinned_events/index.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/saved_object/pinned_events/index.ts @@ -254,19 +254,11 @@ export const convertSavedObjectToSavedPinnedEvent = ( }, identity) ); -// we have to use any here because the SavedObjectAttributes interface is like below -// export interface SavedObjectAttributes { -// [key: string]: SavedObjectAttributes | string | number | boolean | null; -// } -// then this interface does not allow types without index signature -// this is limiting us with our type for now so the easy way was to use any - export const pickSavedPinnedEvent = ( pinnedEventId: string | null, savedPinnedEvent: SavedPinnedEvent, userInfo: AuthenticatedUser | null - // eslint-disable-next-line @typescript-eslint/no-explicit-any -): any => { +) => { const dateNow = new Date().valueOf(); if (pinnedEventId == null) { savedPinnedEvent.created = dateNow; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts b/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts index a2ea7a906fb7b6..9f4158248d6bfe 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts @@ -100,7 +100,9 @@ export const hydrateSavedObjects = async ({ } }); - await server.authSavedObjectsClient?.bulkUpdate(updatedObjects); + await server.authSavedObjectsClient?.bulkUpdate<DecryptedSyntheticsMonitorSavedObject>( + updatedObjects + ); } } catch (e) { server.logger.error(e); diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 768ef135fe5551..74cc38e4f4df0f 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -6,7 +6,7 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { SavedObject, SavedObjectAttributes } from '@kbn/core/types'; +import { SavedObject } from '@kbn/core/types'; export type DeprecationSource = 'Kibana' | 'Elasticsearch'; @@ -57,7 +57,7 @@ export interface ReindexStatusResponse { export const REINDEX_OP_TYPE = 'upgrade-assistant-reindex-operation'; -export interface QueueSettings extends SavedObjectAttributes { +export interface QueueSettings { /** * A Unix timestamp of when the reindex operation was enqueued. * @@ -81,7 +81,7 @@ export interface QueueSettings extends SavedObjectAttributes { startedAt?: number; } -export interface ReindexOptions extends SavedObjectAttributes { +export interface ReindexOptions { /** * Whether to treat the index as if it were closed. This instructs the * reindex strategy to first open the index, perform reindexing and @@ -96,7 +96,7 @@ export interface ReindexOptions extends SavedObjectAttributes { queueSettings?: QueueSettings; } -export interface ReindexOperation extends SavedObjectAttributes { +export interface ReindexOperation { indexName: string; newIndexName: string; status: ReindexStatus; @@ -241,7 +241,7 @@ export interface ResolveIndexResponseFromES { export const ML_UPGRADE_OP_TYPE = 'upgrade-assistant-ml-upgrade-operation'; -export interface MlOperation extends SavedObjectAttributes { +export interface MlOperation { nodeId: string; snapshotId: string; jobId: string; diff --git a/x-pack/test/spaces_api_integration/common/fixtures/spaces_test_plugin/server/plugin.ts b/x-pack/test/spaces_api_integration/common/fixtures/spaces_test_plugin/server/plugin.ts index 1b54ea67554fa3..07cc3bcd28c1b5 100644 --- a/x-pack/test/spaces_api_integration/common/fixtures/spaces_test_plugin/server/plugin.ts +++ b/x-pack/test/spaces_api_integration/common/fixtures/spaces_test_plugin/server/plugin.ts @@ -12,7 +12,7 @@ export class Plugin { public setup(core: CoreSetup) { // called when plugin is setting up during Kibana's startup sequence - core.savedObjects.registerType({ + core.savedObjects.registerType<{ title: string }>({ name: 'sharedtype', hidden: false, namespaceType: 'multiple', @@ -29,7 +29,7 @@ export class Plugin { }, }, }); - core.savedObjects.registerType({ + core.savedObjects.registerType<{ title: string }>({ name: 'isolatedtype', hidden: false, namespaceType: 'single', From 240f0911446f66480c271a203a0cc2a37b3dbb47 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm <matthias.wilhelm@elastic.co> Date: Tue, 13 Sep 2022 10:00:36 +0200 Subject: [PATCH 093/144] [Discover] Refactor Inspector open function to hook (#140466) Co-authored-by: Davis McPhee <davismcphee@hotmail.com> --- .../discover/public/__mocks__/services.ts | 3 ++ .../components/layout/discover_layout.tsx | 26 +++------- .../main/hooks/use_inspector.test.ts | 31 ++++++++++++ .../application/main/hooks/use_inspector.ts | 49 +++++++++++++++++++ 4 files changed, 90 insertions(+), 19 deletions(-) create mode 100644 src/plugins/discover/public/application/main/hooks/use_inspector.test.ts create mode 100644 src/plugins/discover/public/application/main/hooks/use_inspector.ts diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index cd99577962aa46..5a9287d6c768c0 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -55,6 +55,9 @@ export const discoverServiceMock = { }, fieldFormats: fieldFormatsMock, filterManager: dataPlugin.query.filterManager, + inspector: { + open: jest.fn(), + }, uiSettings: { get: jest.fn((key: string) => { if (key === 'fields:popularLimit') { diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 97c79647d32e18..a0262889187e70 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -24,7 +24,7 @@ import { isOfQueryType } from '@kbn/es-query'; import classNames from 'classnames'; import { generateFilters } from '@kbn/data-plugin/public'; import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/public'; -import { InspectorSession } from '@kbn/inspector-plugin/public'; +import { useInspector } from '../../hooks/use_inspector'; import { useDiscoverServices } from '../../../../hooks/use_discover_services'; import { DiscoverNoResults } from '../no_results'; import { LoadingSpinner } from '../loading_spinner/loading_spinner'; @@ -89,7 +89,6 @@ export function DiscoverLayout({ inspector, } = useDiscoverServices(); const { main$, charts$, totalHits$ } = savedSearchData$; - const [inspectorSession, setInspectorSession] = useState<InspectorSession | undefined>(undefined); const dataState: DataMainMsg = useDataState(main$); const viewMode = useMemo(() => { @@ -141,23 +140,12 @@ export function DiscoverLayout({ [dataState.fetchStatus, dataState.foundDocuments, isPlainRecord] ); - const onOpenInspector = useCallback(() => { - // prevent overlapping - setExpandedDoc(undefined); - const session = inspector.open(inspectorAdapters, { - title: savedSearch.title, - }); - setInspectorSession(session); - }, [setExpandedDoc, inspectorAdapters, savedSearch, inspector]); - - useEffect(() => { - return () => { - if (inspectorSession) { - // Close the inspector if this scope is destroyed (e.g. because the user navigates away). - inspectorSession.close(); - } - }; - }, [inspectorSession]); + const onOpenInspector = useInspector({ + setExpandedDoc, + inspector, + inspectorAdapters, + savedSearch, + }); const { columns, onAddColumn, onRemoveColumn } = useColumns({ capabilities, diff --git a/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts b/src/plugins/discover/public/application/main/hooks/use_inspector.test.ts new file mode 100644 index 00000000000000..66c5542f5647a6 --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/use_inspector.test.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { renderHook } from '@testing-library/react-hooks'; +import { discoverServiceMock } from '../../../__mocks__/services'; +import { savedSearchMock } from '../../../__mocks__/saved_search'; +import { useInspector } from './use_inspector'; +import { RequestAdapter } from '@kbn/inspector-plugin/common'; + +describe('test useInspector', () => { + test('inspector open function is executed, expanded doc is closed', async () => { + const setExpandedDoc = jest.fn(); + + const { result } = renderHook(() => { + return useInspector({ + inspectorAdapters: { requests: new RequestAdapter() }, + savedSearch: savedSearchMock, + inspector: discoverServiceMock.inspector, + setExpandedDoc, + }); + }); + result.current(); + expect(setExpandedDoc).toHaveBeenCalledWith(undefined); + expect(discoverServiceMock.inspector.open).toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/discover/public/application/main/hooks/use_inspector.ts b/src/plugins/discover/public/application/main/hooks/use_inspector.ts new file mode 100644 index 00000000000000..c7bcc0ba1cb4b7 --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/use_inspector.ts @@ -0,0 +1,49 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { useCallback, useEffect, useState } from 'react'; +import { + InspectorSession, + RequestAdapter, + Start as InspectorPublicPluginStart, +} from '@kbn/inspector-plugin/public'; +import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { DataTableRecord } from '../../../types'; + +export function useInspector({ + setExpandedDoc, + inspector, + inspectorAdapters, + savedSearch, +}: { + inspectorAdapters: { requests: RequestAdapter }; + savedSearch: SavedSearch; + setExpandedDoc: (doc?: DataTableRecord) => void; + inspector: InspectorPublicPluginStart; +}) { + const [inspectorSession, setInspectorSession] = useState<InspectorSession | undefined>(undefined); + + const onOpenInspector = useCallback(() => { + // prevent overlapping + setExpandedDoc(undefined); + const session = inspector.open(inspectorAdapters, { + title: savedSearch.title, + }); + setInspectorSession(session); + }, [setExpandedDoc, inspectorAdapters, savedSearch, inspector]); + + useEffect(() => { + return () => { + if (inspectorSession) { + // Close the inspector if this scope is destroyed (e.g. because the user navigates away). + inspectorSession.close(); + } + }; + }, [inspectorSession]); + return onOpenInspector; +} From fceadb2e86176420ad29a1f4e99dbc8e9940c595 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda <sergi.massaneda@elastic.co> Date: Tue, 13 Sep 2022 10:31:08 +0200 Subject: [PATCH 094/144] [Security Solution] New useFetch helper hook to include APM monitoring (#140120) * new useQuery wrapper function * remove useQueryBy * monitor indexFieldsSearch * fix test * add apm tracking to timelineSearch * rename to useFetch and improvements Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Steph Milovic <stephanie.milovic@elastic.co> --- .../dashboards/dashboards_table.test.tsx | 11 +- .../dashboards/dashboards_table.tsx | 26 +- .../ml/anomaly/use_anomalies_table_data.ts | 87 ++---- .../use_security_dashboards_table.test.tsx | 10 +- .../use_security_dashboards_table.tsx | 53 ++-- .../common/containers/source/index.test.tsx | 1 + .../containers/source/use_data_view.tsx | 12 +- .../containers/sourcerer/index.test.tsx | 1 + .../public/common/hooks/use_fetch/index.ts | 9 + .../common/hooks/use_fetch/request_names.ts | 14 + .../common/hooks/use_fetch/use_fetch.test.tsx | 295 ++++++++++++++++++ .../common/hooks/use_fetch/use_fetch.ts | 169 ++++++++++ .../timelines/containers/index.test.tsx | 1 + .../public/timelines/containers/index.tsx | 9 + 14 files changed, 595 insertions(+), 103 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/common/hooks/use_fetch/index.ts create mode 100644 x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts create mode 100644 x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.ts diff --git a/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.test.tsx b/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.test.tsx index 03f319b9cc97b8..55811743e4d45d 100644 --- a/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.test.tsx @@ -31,16 +31,15 @@ const DASHBOARD_TABLE_ITEMS = [ }, ]; -const mockUseSecurityDashboardsTableItems = jest.fn(() => DASHBOARD_TABLE_ITEMS); +const mockUseSecurityDashboardsTableItems = jest.fn(() => ({ + items: DASHBOARD_TABLE_ITEMS, + isLoading: false, +})); jest.mock('../../containers/dashboards/use_security_dashboards_table', () => { const actual = jest.requireActual('../../containers/dashboards/use_security_dashboards_table'); return { ...actual, - useSecurityDashboardsTable: () => { - const columns = actual.useSecurityDashboardsTableColumns(); - const items = mockUseSecurityDashboardsTableItems(); - return { columns, items }; - }, + useSecurityDashboardsTableItems: () => mockUseSecurityDashboardsTableItems(), }; }); diff --git a/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.tsx b/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.tsx index ee99a9966ab8aa..ba933becda53a9 100644 --- a/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/dashboards/dashboards_table.tsx @@ -9,7 +9,19 @@ import React, { useEffect, useMemo, useState } from 'react'; import { debounce } from 'lodash'; import type { Search } from '@elastic/eui'; import { EuiInMemoryTable } from '@elastic/eui'; -import { useSecurityDashboardsTable } from '../../containers/dashboards/use_security_dashboards_table'; +import { i18n } from '@kbn/i18n'; +import { + useSecurityDashboardsTableItems, + useSecurityDashboardsTableColumns, +} from '../../containers/dashboards/use_security_dashboards_table'; +import { useAppToasts } from '../../hooks/use_app_toasts'; + +export const DASHBOARDS_QUERY_ERROR = i18n.translate( + 'xpack.securitySolution.dashboards.queryError', + { + defaultMessage: 'Error retrieving security dashboards', + } +); /** wait this many ms after the user completes typing before applying the filter input */ const INPUT_TIMEOUT = 250; @@ -22,7 +34,10 @@ const DASHBOARDS_TABLE_SORTING = { } as const; export const DashboardsTable: React.FC = () => { - const { items, columns } = useSecurityDashboardsTable(); + const { items, isLoading, error } = useSecurityDashboardsTableItems(); + const columns = useSecurityDashboardsTableColumns(); + const { addError } = useAppToasts(); + const [filteredItems, setFilteredItems] = useState(items); const [searchQuery, setSearchQuery] = useState(''); @@ -52,6 +67,12 @@ export const DashboardsTable: React.FC = () => { } }, [items, searchQuery]); + useEffect(() => { + if (error) { + addError(error, { title: DASHBOARDS_QUERY_ERROR }); + } + }, [error, addError]); + return ( <EuiInMemoryTable data-test-subj="dashboardsTable" @@ -60,6 +81,7 @@ export const DashboardsTable: React.FC = () => { search={search} pagination={true} sorting={DASHBOARDS_TABLE_SORTING} + loading={isLoading} /> ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts index 06732f83f2af7a..5fa33c8becfcab 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/anomaly/use_anomalies_table_data.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { useState, useEffect, useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DEFAULT_ANOMALY_SCORE } from '../../../../../common/constants'; import { anomaliesTableData } from '../api/anomalies_table_data'; @@ -14,6 +14,7 @@ import type { InfluencerInput, Anomalies, CriteriaFields } from '../types'; import * as i18n from './translations'; import { useTimeZone, useUiSetting$ } from '../../../lib/kibana'; import { useAppToasts } from '../../../hooks/use_app_toasts'; +import { useFetch, REQUEST_NAMES } from '../../../hooks/use_fetch'; import { useMlCapabilities } from '../hooks/use_ml_capabilities'; import { hasMlUserPermissions } from '../../../../../common/machine_learning/has_ml_user_permissions'; @@ -63,11 +64,9 @@ export const useAnomaliesTableData = ({ jobIds, aggregationInterval, }: Args): Return => { - const [tableData, setTableData] = useState<Anomalies | null>(null); const mlCapabilities = useMlCapabilities(); const isMlUser = hasMlUserPermissions(mlCapabilities); - const [loading, setLoading] = useState(true); const { addError } = useAppToasts(); const timeZone = useTimeZone(); const [anomalyScore] = useUiSetting$<number>(DEFAULT_ANOMALY_SCORE); @@ -75,62 +74,35 @@ export const useAnomaliesTableData = ({ const startDateMs = useMemo(() => new Date(startDate).getTime(), [startDate]); const endDateMs = useMemo(() => new Date(endDate).getTime(), [endDate]); - useEffect(() => { - let isSubscribed = true; - const abortCtrl = new AbortController(); - setLoading(true); + const { + fetch, + data = null, + isLoading, + error, + } = useFetch(REQUEST_NAMES.ANOMALIES_TABLE, anomaliesTableData, { disabled: skip }); - async function fetchAnomaliesTableData( - influencersInput: InfluencerInput[], - criteriaFieldsInput: CriteriaFields[], - earliestMs: number, - latestMs: number - ) { - if (skip) { - setLoading(false); - } else if (isMlUser && !skip && jobIds.length > 0) { - try { - const data = await anomaliesTableData( - { - jobIds, - criteriaFields: criteriaFieldsInput, - influencersFilterQuery: filterQuery, - aggregationInterval, - threshold: getThreshold(anomalyScore, threshold), - earliestMs, - latestMs, - influencers: influencersInput, - dateFormatTz: timeZone, - maxRecords: 500, - maxExamples: 10, - }, - abortCtrl.signal - ); - if (isSubscribed) { - setTableData(data); - setLoading(false); - } - } catch (error) { - if (isSubscribed) { - addError(error, { title: i18n.SIEM_TABLE_FETCH_FAILURE }); - setLoading(false); - } - } - } else if (!isMlUser && isSubscribed) { - setLoading(false); - } else if (jobIds.length === 0 && isSubscribed) { - setLoading(false); - } else if (isSubscribed) { - setTableData(null); - setLoading(true); - } + useEffect(() => { + if (error) { + addError(error, { title: i18n.SIEM_TABLE_FETCH_FAILURE }); } + }, [error, addError]); - fetchAnomaliesTableData(influencers, criteriaFields, startDateMs, endDateMs); - return () => { - isSubscribed = false; - abortCtrl.abort(); - }; + useEffect(() => { + if (isMlUser && jobIds.length > 0) { + fetch({ + jobIds, + criteriaFields, + influencersFilterQuery: filterQuery, + aggregationInterval, + threshold: getThreshold(anomalyScore, threshold), + earliestMs: startDateMs, + latestMs: endDateMs, + influencers, + dateFormatTz: timeZone, + maxRecords: 500, + maxExamples: 10, + }); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, [ // eslint-disable-next-line react-hooks/exhaustive-deps @@ -139,12 +111,11 @@ export const useAnomaliesTableData = ({ influencersOrCriteriaToString(criteriaFields), startDateMs, endDateMs, - skip, isMlUser, aggregationInterval, // eslint-disable-next-line react-hooks/exhaustive-deps jobIds.sort().join(), ]); - return [loading, tableData]; + return [isLoading, data]; }; diff --git a/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.test.tsx b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.test.tsx index 43da2bd760b3b3..bc02fb3b205d68 100644 --- a/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.test.tsx @@ -99,9 +99,9 @@ describe('Security Dashboards Table hooks', () => { it('should return a memoized value when rerendered', async () => { const { result, rerender } = await renderUseSecurityDashboardsTableItems(); - const result1 = result.current; + const result1 = result.current.items; act(() => rerender()); - const result2 = result.current; + const result2 = result.current.items; expect(result1).toBe(result2); }); @@ -110,7 +110,7 @@ describe('Security Dashboards Table hooks', () => { const { result } = await renderUseSecurityDashboardsTableItems(); const [dashboard1, dashboard2] = DASHBOARDS_RESPONSE; - expect(result.current).toStrictEqual([ + expect(result.current.items).toStrictEqual([ { ...dashboard1, title: dashboard1.attributes.title, @@ -148,7 +148,7 @@ describe('Security Dashboards Table hooks', () => { }); it('returns a memoized value', async () => { - const { result, rerender } = await renderUseSecurityDashboardsTableItems(); + const { result, rerender } = renderUseDashboardsTableColumns(); const result1 = result.current; act(() => rerender()); @@ -163,7 +163,7 @@ describe('Security Dashboards Table hooks', () => { const { result: columnsResult } = renderUseDashboardsTableColumns(); const result = render( - <EuiBasicTable items={itemsResult.current} columns={columnsResult.current} />, + <EuiBasicTable items={itemsResult.current.items} columns={columnsResult.current} />, { wrapper: TestProviders, } diff --git a/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx index 0fe9bbede41530..71fad3639dc5c6 100644 --- a/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/dashboards/use_security_dashboards_table.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState, useEffect, useMemo, useCallback } from 'react'; +import React, { useEffect, useMemo, useCallback } from 'react'; import type { MouseEventHandler } from 'react'; import type { EuiBasicTableColumn } from '@elastic/eui'; import type { SavedObjectAttributes } from '@kbn/securitysolution-io-ts-alerting-types'; @@ -14,6 +14,7 @@ import { getSecurityDashboards } from './utils'; import { LinkAnchor } from '../../components/links'; import { useKibana, useNavigateTo } from '../../lib/kibana'; import * as i18n from './translations'; +import { useFetch, REQUEST_NAMES } from '../../hooks/use_fetch'; export interface DashboardTableItem extends SavedObject<SavedObjectAttributes> { title?: string; @@ -23,37 +24,33 @@ export interface DashboardTableItem extends SavedObject<SavedObjectAttributes> { const EMPTY_DESCRIPTION = '-' as const; export const useSecurityDashboardsTableItems = () => { - const [dashboardItems, setDashboardItems] = useState<DashboardTableItem[]>([]); const { savedObjects: { client: savedObjectsClient }, } = useKibana().services; - useEffect(() => { - let ignore = false; - const fetchDashboards = async () => { - if (savedObjectsClient) { - const securityDashboards = await getSecurityDashboards(savedObjectsClient); - - if (!ignore) { - setDashboardItems( - securityDashboards.map((securityDashboard) => ({ - ...securityDashboard, - title: securityDashboard.attributes.title?.toString() ?? undefined, - description: securityDashboard.attributes.description?.toString() ?? undefined, - })) - ); - } - } - }; + const { fetch, data, isLoading, error } = useFetch( + REQUEST_NAMES.SECURITY_DASHBOARDS, + getSecurityDashboards + ); - fetchDashboards(); + useEffect(() => { + if (savedObjectsClient) { + fetch(savedObjectsClient); + } + }, [fetch, savedObjectsClient]); - return () => { - ignore = true; - }; - }, [savedObjectsClient]); + const items = useMemo(() => { + if (!data) { + return []; + } + return data.map((securityDashboard) => ({ + ...securityDashboard, + title: securityDashboard.attributes.title?.toString() ?? undefined, + description: securityDashboard.attributes.description?.toString() ?? undefined, + })); + }, [data]); - return dashboardItems; + return { items, isLoading, error }; }; export const useSecurityDashboardsTableColumns = (): Array< @@ -104,9 +101,3 @@ export const useSecurityDashboardsTableColumns = (): Array< return columns; }; - -export const useSecurityDashboardsTable = () => { - const items = useSecurityDashboardsTableItems(); - const columns = useSecurityDashboardsTableColumns(); - return { items, columns }; -}; diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx index 40a473de306871..41383d4a0eb722 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.test.tsx @@ -24,6 +24,7 @@ jest.mock('react-redux', () => { }; }); jest.mock('../../lib/kibana'); +jest.mock('../../lib/apm/use_track_http_request'); describe('source/index.tsx', () => { describe('getAllBrowserFields', () => { diff --git a/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx b/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx index 51ad895b56f0ca..c259f8843263af 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx @@ -25,6 +25,8 @@ import { sourcererActions } from '../../store/sourcerer'; import * as i18n from './translations'; import { SourcererScopeName } from '../../store/sourcerer/model'; import { getSourcererDataView } from '../sourcerer/api'; +import { useTrackHttpRequest } from '../../lib/apm/use_track_http_request'; +import { APP_UI_ID } from '../../../../common/constants'; export type IndexFieldSearch = (param: { dataViewId: string; @@ -86,6 +88,7 @@ export const useDataView = (): { const searchSubscription$ = useRef<Record<string, Subscription>>({}); const dispatch = useDispatch(); const { addError, addWarning } = useAppToasts(); + const { startTracking } = useTrackHttpRequest(); const setLoading = useCallback( ({ id, loading }: { id: string; loading: boolean }) => { @@ -112,6 +115,9 @@ export const useDataView = (): { [dataViewId]: new AbortController(), }; setLoading({ id: dataViewId, loading: true }); + + const { endTracking } = startTracking({ name: `${APP_UI_ID} indexFieldsSearch` }); + if (needToBeInit) { const dataViewToUpdate = await getSourcererDataView( dataViewId, @@ -139,6 +145,8 @@ export const useDataView = (): { .subscribe({ next: async (response) => { if (isCompleteResponse(response)) { + endTracking('success'); + const patternString = response.indicesExist.sort().join(); if (needToBeInit && scopeId) { dispatch( @@ -167,6 +175,7 @@ export const useDataView = (): { }) ); } else if (isErrorResponse(response)) { + endTracking('invalid'); setLoading({ id: dataViewId, loading: false }); addWarning(i18n.ERROR_BEAT_FIELDS); } @@ -174,6 +183,7 @@ export const useDataView = (): { resolve(); }, error: (msg) => { + endTracking('error'); if (msg.message === DELETED_SECURITY_SOLUTION_DATA_VIEW) { // reload app if security solution data view is deleted return location.reload(); @@ -200,7 +210,7 @@ export const useDataView = (): { } return asyncSearch(); }, - [addError, addWarning, data.search, dispatch, setLoading] + [addError, addWarning, data.search, dispatch, setLoading, startTracking] ); useEffect(() => { diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx index b99547db88ba40..9be9c1266c1c95 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx @@ -46,6 +46,7 @@ const mockRouteSpy: RouteSpyState = { }; const mockDispatch = jest.fn(); const mockUseUserInfo = useUserInfo as jest.Mock; +jest.mock('../../lib/apm/use_track_http_request'); jest.mock('../../../detections/components/user_info'); jest.mock('./api'); jest.mock('../../utils/global_query_string'); diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/index.ts b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/index.ts new file mode 100644 index 00000000000000..fae594e8414ce4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/index.ts @@ -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 { useFetch } from './use_fetch'; +export { REQUEST_NAMES } from './request_names'; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts new file mode 100644 index 00000000000000..cadfd2a68fa326 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/request_names.ts @@ -0,0 +1,14 @@ +/* + * 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 { APP_UI_ID } from '../../../../common/constants'; + +export const REQUEST_NAMES = { + SECURITY_DASHBOARDS: `${APP_UI_ID} fetch security dashboards`, + ANOMALIES_TABLE: `${APP_UI_ID} fetch anomalies table data`, +} as const; + +export type RequestName = typeof REQUEST_NAMES[keyof typeof REQUEST_NAMES]; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx new file mode 100644 index 00000000000000..13d758ed7a596e --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.test.tsx @@ -0,0 +1,295 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import type { RequestName } from './request_names'; +import type { OptionsParam, RequestFnParam, Result } from './use_fetch'; +import { useFetch } from './use_fetch'; + +export const mockEndTracking = jest.fn(); +export const mockStartTracking = jest.fn(() => ({ endTracking: mockEndTracking })); +jest.mock('../../lib/apm/use_track_http_request', () => ({ + useTrackHttpRequest: jest.fn(() => ({ + startTracking: mockStartTracking, + })), +})); + +const requestName = 'test name' as RequestName; + +const parameters = { + some: 'fakeParam', +}; +type Parameters = typeof parameters; + +const response = 'someData'; +const mockFetchFn = jest.fn(async (_: Parameters) => response); + +type UseFetchParams = [RequestName, RequestFnParam<Parameters, string>, OptionsParam<Parameters>]; + +const abortController = new AbortController(); + +const renderUseFetch = (options?: OptionsParam<Parameters>) => + renderHook<UseFetchParams, Result<Parameters, string, unknown>>(() => + useFetch(requestName, mockFetchFn, options) + ); + +describe('useFetch', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('init', async () => { + const { result } = renderUseFetch(); + + const { data, isLoading, error } = result.current; + + expect(data).toEqual(undefined); + expect(isLoading).toEqual(false); + expect(error).toEqual(undefined); + + expect(mockFetchFn).not.toHaveBeenCalled(); + }); + + it('should call fetch', async () => { + const { result, waitForNextUpdate } = renderUseFetch(); + + expect(result.current.data).toEqual(undefined); + expect(result.current.isLoading).toEqual(false); + expect(result.current.error).toEqual(undefined); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(result.current.data).toEqual(response); + expect(result.current.isLoading).toEqual(false); + expect(result.current.error).toEqual(undefined); + expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); + }); + + it('should call fetch if initialParameters option defined', async () => { + const { result, waitForNextUpdate } = renderUseFetch({ initialParameters: parameters }); + + expect(result.current.data).toEqual(undefined); + expect(result.current.isLoading).toEqual(true); + expect(result.current.error).toEqual(undefined); + + expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); + + await act(async () => { + await waitForNextUpdate(); + }); + + expect(result.current.data).toEqual(response); + expect(result.current.isLoading).toEqual(false); + expect(result.current.error).toEqual(undefined); + }); + + it('should refetch with same parameters', async () => { + const { result, waitForNextUpdate } = renderUseFetch({ initialParameters: parameters }); + + expect(mockFetchFn).toHaveBeenCalledTimes(1); + expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); + + await act(async () => { + result.current.refetch(); + await waitForNextUpdate(); + }); + + expect(mockFetchFn).toHaveBeenCalledTimes(1); + expect(mockFetchFn).toHaveBeenCalledWith(parameters, abortController.signal); + }); + + it('should not call fetch if disabled option defined', async () => { + const { result, waitForNextUpdate } = renderUseFetch({ + initialParameters: parameters, + disabled: true, + }); + + expect(result.current.data).toEqual(undefined); + expect(result.current.isLoading).toEqual(true); + expect(result.current.error).toEqual(undefined); + + expect(mockFetchFn).not.toHaveBeenCalled(); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(result.current.data).toEqual(undefined); + expect(result.current.isLoading).toEqual(true); + expect(result.current.error).toEqual(undefined); + expect(mockFetchFn).not.toHaveBeenCalled(); + }); + + it('should ignore state change if component is unmounted', async () => { + mockFetchFn.mockImplementationOnce(async () => { + unmount(); + return response; + }); + + const { result, waitForNextUpdate, unmount } = renderUseFetch(); + + expect(result.current.data).toEqual(undefined); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(result.current.data).toEqual(undefined); + }); + + it('should ignore state change if error but component is unmounted', async () => { + mockFetchFn.mockImplementationOnce(async () => { + unmount(); + throw new Error(); + }); + + const { result, waitForNextUpdate, unmount } = renderUseFetch(); + + expect(result.current.error).toEqual(undefined); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(result.current.error).toEqual(undefined); + }); + + it('should abort initial request if fetch is called', async () => { + const firstAbortCtrl = new AbortController(); + const abortSpy = jest.spyOn(window, 'AbortController').mockReturnValueOnce(firstAbortCtrl); + + const { result, waitForNextUpdate } = renderUseFetch({ initialParameters: parameters }); + + mockFetchFn.mockImplementationOnce(async () => { + result.current.fetch(parameters); + return response; + }); + + await act(async () => { + await waitForNextUpdate(); + }); + + expect(firstAbortCtrl.signal.aborted).toEqual(true); + + abortSpy.mockRestore(); + }); + + it('should abort first request if fetch is called twice', async () => { + const firstAbortCtrl = new AbortController(); + const abortSpy = jest.spyOn(window, 'AbortController').mockReturnValueOnce(firstAbortCtrl); + + const { result, waitForNextUpdate } = renderUseFetch(); + + mockFetchFn.mockImplementationOnce(async () => { + result.current.fetch(parameters); + return response; + }); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(firstAbortCtrl.signal.aborted).toEqual(true); + + abortSpy.mockRestore(); + }); + + describe('APM tracking', () => { + it('should track with request name', async () => { + const { result, waitForNextUpdate } = renderUseFetch(); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(mockStartTracking).toHaveBeenCalledTimes(1); + expect(mockStartTracking).toHaveBeenCalledWith({ name: requestName }); + }); + + it('should track each request', async () => { + const { result, waitForNextUpdate } = renderUseFetch({ + initialParameters: parameters, + }); + + await act(async () => { + await waitForNextUpdate(); + }); + + expect(mockFetchFn).toHaveBeenCalledTimes(1); + expect(mockStartTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockStartTracking).toHaveBeenCalledWith({ name: requestName }); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(mockFetchFn).toHaveBeenCalledTimes(2); + expect(mockStartTracking).toHaveBeenCalledTimes(2); + expect(mockEndTracking).toHaveBeenCalledTimes(2); + }); + + it('should end success', async () => { + const { result, waitForNextUpdate } = renderUseFetch(); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledWith('success'); + }); + + it('should end aborted', async () => { + const abortCtrl = new AbortController(); + const abortSpy = jest.spyOn(window, 'AbortController').mockReturnValue(abortCtrl); + + mockFetchFn.mockImplementationOnce(async () => { + abortCtrl.abort(); + throw Error('request aborted'); + }); + + const { result, waitForNextUpdate } = renderUseFetch(); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledWith('aborted'); + + abortSpy.mockRestore(); + }); + + it('should end error', async () => { + mockFetchFn.mockImplementationOnce(async () => { + throw Error('request error'); + }); + + const { result, waitForNextUpdate } = renderUseFetch(); + + await act(async () => { + result.current.fetch(parameters); + await waitForNextUpdate(); + }); + + expect(mockEndTracking).toHaveBeenCalledTimes(1); + expect(mockEndTracking).toHaveBeenCalledWith('error'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.ts b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.ts new file mode 100644 index 00000000000000..330b47569b3e94 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/hooks/use_fetch/use_fetch.ts @@ -0,0 +1,169 @@ +/* + * 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 { useCallback, useEffect, useReducer } from 'react'; +import type { Reducer } from 'react'; +import { useTrackHttpRequest } from '../../lib/apm/use_track_http_request'; +import type { RequestName } from './request_names'; + +interface ResultState<Response, Error> { + /** + * The `data` will contain the raw response of the latest request executed. + * It is initialized to `undefined`. + */ + data?: Response; + isLoading: boolean; + /** + * The `error` will contain the error of the latest request executed. + * It is reset when a success response is completed. + */ + error?: Error; +} + +export interface Result<Parameters, Response, Error> extends ResultState<Response, Error> { + /** + * The `fetch` function starts a request with the parameters. + * It aborts any previous pending request and starts a new request, every time it is called. + * Optimizations are delegated to the consumer of the hook. + */ + fetch: (parameters: Parameters) => void; + /** + * The `refetch` function restarts a request with the latest parameters used. + * It aborts any previous pending request + */ + refetch: () => void; +} + +export type RequestFnParam<Parameters, Response> = ( + /** + * The parameters that will be passed to the fetch function provided. + */ + parameters: Parameters, + /** + * The abort signal. Call `signal.abort()` to abort the request. + */ + signal: AbortController['signal'] +) => Promise<Response>; + +export interface OptionsParam<Parameters> { + /** + * Disables the fetching and aborts any pending request when is set to `true`. + */ + disabled?: boolean; + /** + * Set `initialParameters` to start fetching immediately when the hook is called, without having to call the `fetch` function. + */ + initialParameters?: Parameters; +} + +interface State<Parameters, Response, Error> extends ResultState<Response, Error> { + parameters?: Parameters; +} + +type Action<Parameters, Response, Error> = + | { type: 'FETCH_INIT'; payload: Parameters } + | { type: 'FETCH_SUCCESS'; payload: Response } + | { type: 'FETCH_FAILURE'; payload?: Error } + | { type: 'FETCH_REPEAT' }; + +const requestReducer = <Parameters, Response, Error>( + state: State<Parameters, Response, Error>, + action: Action<Parameters, Response, Error> +): State<Parameters, Response, Error> => { + switch (action.type) { + case 'FETCH_INIT': + return { + ...state, + parameters: action.payload, + isLoading: true, + }; + case 'FETCH_SUCCESS': + return { + ...state, + data: action.payload, + isLoading: false, + error: undefined, + }; + case 'FETCH_FAILURE': + return { + ...state, + error: action.payload, + isLoading: false, + }; + case 'FETCH_REPEAT': + return { + ...state, + isLoading: true, + }; + default: + return state; + } +}; + +/** + * `useFetch` is a generic hook that simplifies the async request queries implementation. + * It provides: APM monitoring, abort control, error handling and refetching. + * @param requestName The unique name of the request. It is used for APM tracking, it should be descriptive. + * @param fetchFn The function provided to execute the fetch request. It should accept the request `parameters` and the abort `signal`. + * @param options Additional options. + */ +export const useFetch = <Parameters, Response, Error extends unknown>( + requestName: RequestName, + fetchFn: RequestFnParam<Parameters, Response>, + { disabled = false, initialParameters }: OptionsParam<Parameters> = {} +): Result<Parameters, Response, Error> => { + const { startTracking } = useTrackHttpRequest(); + + const [{ parameters, data, isLoading, error }, dispatch] = useReducer< + Reducer<State<Parameters, Response, Error>, Action<Parameters, Response, Error>> + >(requestReducer, { + data: undefined, + isLoading: initialParameters !== undefined, // isLoading state is used internally to control fetch executions + error: undefined, + parameters: initialParameters, + }); + + const fetch = useCallback( + (param: Parameters) => dispatch({ type: 'FETCH_INIT', payload: param }), + [] + ); + const refetch = useCallback(() => dispatch({ type: 'FETCH_REPEAT' }), []); + + useEffect(() => { + if (isLoading === false || parameters === undefined || disabled) { + return; + } + + let ignore = false; + const abortController = new AbortController(); + + const executeFetch = async () => { + const { endTracking } = startTracking({ name: requestName }); + try { + const response = await fetchFn(parameters, abortController.signal); + endTracking('success'); + if (!ignore) { + dispatch({ type: 'FETCH_SUCCESS', payload: response }); + } + } catch (err) { + endTracking(abortController.signal.aborted ? 'aborted' : 'error'); + if (!ignore) { + dispatch({ type: 'FETCH_FAILURE', payload: err }); + } + } + }; + + executeFetch(); + + return () => { + ignore = true; + abortController.abort(); + }; + }, [isLoading, parameters, disabled, fetchFn, startTracking, requestName]); + + return { fetch, refetch, data, isLoading, error }; +}; diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx index 00197a8719a6d8..9ef5fbfd0a203c 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx @@ -28,6 +28,7 @@ const mockEvents = mockTimelineData.filter((i, index) => index <= 11); const mockSearch = jest.fn(); +jest.mock('../../common/lib/apm/use_track_http_request'); jest.mock('../../common/hooks/use_experimental_features'); const useIsExperimentalFeatureEnabledMock = useIsExperimentalFeatureEnabled as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx index 6024c4613f265c..700d5d9d1255e3 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx @@ -43,6 +43,8 @@ import type { TimelineEqlResponse, } from '../../../common/search_strategy/timeline/events/eql'; import { useAppToasts } from '../../common/hooks/use_app_toasts'; +import { useTrackHttpRequest } from '../../common/lib/apm/use_track_http_request'; +import { APP_UI_ID } from '../../../common/constants'; export interface TimelineArgs { events: TimelineItem[]; @@ -156,6 +158,7 @@ export const useTimelineEvents = ({ null ); const prevTimelineRequest = useRef<TimelineRequest<typeof language> | null>(null); + const { startTracking } = useTrackHttpRequest(); const clearSignalsState = useCallback(() => { if (id != null && detectionsTimelineIds.some((timelineId) => timelineId === id)) { @@ -219,6 +222,8 @@ export const useTimelineEvents = ({ prevTimelineRequest.current = request; abortCtrl.current = new AbortController(); setLoading(true); + const { endTracking } = startTracking({ name: `${APP_UI_ID} timeline events search` }); + searchSubscription$.current = data.search .search<TimelineRequest<typeof language>, TimelineResponse<typeof language>>(request, { strategy: @@ -230,6 +235,7 @@ export const useTimelineEvents = ({ .subscribe({ next: (response) => { if (isCompleteResponse(response)) { + endTracking('success'); setLoading(false); setTimelineResponse((prevResponse) => { const newTimelineResponse = { @@ -257,12 +263,14 @@ export const useTimelineEvents = ({ }); searchSubscription$.current.unsubscribe(); } else if (isErrorResponse(response)) { + endTracking('invalid'); setLoading(false); addWarning(i18n.ERROR_TIMELINE_EVENTS); searchSubscription$.current.unsubscribe(); } }, error: (msg) => { + endTracking(abortCtrl.current.signal.aborted ? 'aborted' : 'error'); setLoading(false); data.search.showError(msg); searchSubscription$.current.unsubscribe(); @@ -317,6 +325,7 @@ export const useTimelineEvents = ({ pageName, skip, id, + startTracking, data.search, dataViewId, setUpdated, From e490ca9e61ff66d019ee0ba0992c3ebf23d8abca Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger <walter.rafelsberger@elastic.co> Date: Tue, 13 Sep 2022 10:48:25 +0200 Subject: [PATCH 095/144] [ML] Fix package imports. (#140488) Previously, some types were not available yet in packages that needed to imported via kibana-core. Since they are now available, this PR replaces our own temporary types with the correct imports. --- x-pack/packages/ml/agg_utils/BUILD.bazel | 1 + .../ml/agg_utils/src/fetch_agg_intervals.ts | 3 ++- .../agg_utils/src/fetch_histograms_for_fields.ts | 2 +- x-pack/packages/ml/agg_utils/src/types.ts | 15 --------------- x-pack/packages/ml/aiops_utils/BUILD.bazel | 1 + .../ml/aiops_utils/src/accept_compression.ts | 7 +------ .../packages/ml/aiops_utils/src/stream_factory.ts | 12 ++---------- 7 files changed, 8 insertions(+), 33 deletions(-) diff --git a/x-pack/packages/ml/agg_utils/BUILD.bazel b/x-pack/packages/ml/agg_utils/BUILD.bazel index b9b4533b56e37d..8841369749200d 100644 --- a/x-pack/packages/ml/agg_utils/BUILD.bazel +++ b/x-pack/packages/ml/agg_utils/BUILD.bazel @@ -68,6 +68,7 @@ TYPES_DEPS = [ "@npm//@types/lodash", "@npm//@elastic/elasticsearch", "@npm//tslib", + "//packages/core/elasticsearch/core-elasticsearch-server:npm_module_types", "//packages/kbn-field-types:npm_module_types", "//x-pack/packages/ml/is_populated_object:npm_module_types", "//x-pack/packages/ml/string_hash:npm_module_types", diff --git a/x-pack/packages/ml/agg_utils/src/fetch_agg_intervals.ts b/x-pack/packages/ml/agg_utils/src/fetch_agg_intervals.ts index 1d6b3f781f901f..338f55ad754c29 100644 --- a/x-pack/packages/ml/agg_utils/src/fetch_agg_intervals.ts +++ b/x-pack/packages/ml/agg_utils/src/fetch_agg_intervals.ts @@ -9,13 +9,14 @@ import { get } from 'lodash'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import { stringHash } from '@kbn/ml-string-hash'; import { buildSamplerAggregation } from './build_sampler_aggregation'; import { getSamplerAggregationsResponsePath } from './get_sampler_aggregations_response_path'; -import type { ElasticsearchClient, HistogramField, NumericColumnStatsMap } from './types'; +import type { HistogramField, NumericColumnStatsMap } from './types'; const MAX_CHART_COLUMNS = 20; diff --git a/x-pack/packages/ml/agg_utils/src/fetch_histograms_for_fields.ts b/x-pack/packages/ml/agg_utils/src/fetch_histograms_for_fields.ts index 1e8e2667c0aac0..a921eaeae370bb 100644 --- a/x-pack/packages/ml/agg_utils/src/fetch_histograms_for_fields.ts +++ b/x-pack/packages/ml/agg_utils/src/fetch_histograms_for_fields.ts @@ -9,6 +9,7 @@ import get from 'lodash/get'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { isPopulatedObject } from '@kbn/ml-is-populated-object'; import { stringHash } from '@kbn/ml-string-hash'; @@ -18,7 +19,6 @@ import { fetchAggIntervals } from './fetch_agg_intervals'; import { getSamplerAggregationsResponsePath } from './get_sampler_aggregations_response_path'; import type { AggCardinality, - ElasticsearchClient, HistogramField, NumericColumnStats, NumericColumnStatsMap, diff --git a/x-pack/packages/ml/agg_utils/src/types.ts b/x-pack/packages/ml/agg_utils/src/types.ts index 352616d74cb3e6..173c3b69ba7614 100644 --- a/x-pack/packages/ml/agg_utils/src/types.ts +++ b/x-pack/packages/ml/agg_utils/src/types.ts @@ -5,23 +5,8 @@ * 2.0. */ -import type { Client } from '@elastic/elasticsearch'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; -// TODO Temporary type definition until we can import from `@kbn/core`. -// Copied from src/core/server/elasticsearch/client/types.ts -// as these types aren't part of any package yet. Once they are, remove this completely - -/** - * Client used to query the elasticsearch cluster. - * @deprecated At some point use the one from src/core/server/elasticsearch/client/types.ts when it is made into a package. If it never is, then keep using this one. - * @public - */ -export type ElasticsearchClient = Omit< - Client, - 'connectionPool' | 'serializer' | 'extend' | 'close' | 'diagnostic' ->; - interface FieldAggCardinality { field: string; percent?: any; diff --git a/x-pack/packages/ml/aiops_utils/BUILD.bazel b/x-pack/packages/ml/aiops_utils/BUILD.bazel index a7f8d5849ccb34..0e8edc688c6179 100644 --- a/x-pack/packages/ml/aiops_utils/BUILD.bazel +++ b/x-pack/packages/ml/aiops_utils/BUILD.bazel @@ -64,6 +64,7 @@ TYPES_DEPS = [ "@npm//@types/node", "@npm//@types/jest", "@npm//@types/react", + "//packages/core/elasticsearch/core-elasticsearch-server:npm_module_types", "//packages/kbn-logging:npm_module_types" ] diff --git a/x-pack/packages/ml/aiops_utils/src/accept_compression.ts b/x-pack/packages/ml/aiops_utils/src/accept_compression.ts index 690f5d21c52a8b..40424fec7ed11a 100644 --- a/x-pack/packages/ml/aiops_utils/src/accept_compression.ts +++ b/x-pack/packages/ml/aiops_utils/src/accept_compression.ts @@ -5,12 +5,7 @@ * 2.0. */ -/** - * TODO: Replace these with kbn packaged versions once we have those available to us. - * At the moment imports from runtime plugins into packages are not supported. - * import type { Headers } from '@kbn/core/server'; - */ -type Headers = Record<string, string | string[] | undefined>; +import type { Headers } from '@kbn/core-http-server'; function containsGzip(s: string) { return s diff --git a/x-pack/packages/ml/aiops_utils/src/stream_factory.ts b/x-pack/packages/ml/aiops_utils/src/stream_factory.ts index 7d685369e4d10e..16bc2abe193063 100644 --- a/x-pack/packages/ml/aiops_utils/src/stream_factory.ts +++ b/x-pack/packages/ml/aiops_utils/src/stream_factory.ts @@ -9,16 +9,10 @@ import { Stream } from 'stream'; import * as zlib from 'zlib'; import type { Logger } from '@kbn/logging'; +import type { Headers, ResponseHeaders } from '@kbn/core-http-server'; import { acceptCompression } from './accept_compression'; -/** - * TODO: Replace these with kbn packaged versions once we have those available to us. - * At the moment imports from runtime plugins into packages are not supported. - * import type { Headers } from '@kbn/core/server'; - */ -type Headers = Record<string, string | string[] | undefined>; - // We need this otherwise Kibana server will crash with a 'ERR_METHOD_NOT_IMPLEMENTED' error. class ResponseStream extends Stream.PassThrough { flush() {} @@ -35,9 +29,7 @@ interface StreamFactoryReturnType<T = unknown> { push: (d: T) => void; responseWithHeaders: { body: zlib.Gzip | ResponseStream; - // TODO: Replace these with kbn packaged versions once we have those available to us. - // At the moment imports from runtime plugins into packages are not supported. - headers?: any; + headers?: ResponseHeaders; }; } From f821e6e2ded9ed8aaf7c3dd93f644c50b678862f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= <david.sanchezsoler@elastic.co> Date: Tue, 13 Sep 2022 10:50:53 +0200 Subject: [PATCH 096/144] [Security Solution] [Endpoint] Show es_connection error in fleet agent details (#140167) * Shows es_connection error in fleet agent details. Include new extension point for generic package errors list * Use filter instead of for loop * Updates wrong description comment * Rename variable and use a new one to improve readability * Updates data-test-subj names * Update x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts Co-authored-by: Joe Peeples <joe.peeples@elastic.co> * Remove useMemo and fix typo in test-subj name * Remove temporary url in order to remove UI link until we get the final troubleshooting url * Update x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts Co-authored-by: Joe Peeples <joe.peeples@elastic.co> * Uses filter instead of for loop to get the agent components Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Joe Peeples <joe.peeples@elastic.co> --- packages/kbn-doc-links/src/get_doc_links.ts | 4 + packages/kbn-doc-links/src/types.ts | 3 + .../fleet/common/types/models/agent.ts | 3 +- .../fleet/dev_docs/fleet_ui_extensions.md | 6 ++ .../agent_details_integrations.tsx | 40 ++++++++- x-pack/plugins/fleet/public/index.ts | 2 + .../fleet/public/types/ui_extensions.ts | 20 +++++ .../package_action_formatter.ts | 81 +++++++++++++++++++ .../package_action_item_error.tsx | 53 ++++++++++++ .../endpoint_generic_errors_list.tsx | 52 ++++++++++++ .../lazy_endpoint_generic_errors_list.tsx | 34 ++++++++ .../security_solution/public/plugin.tsx | 6 ++ 12 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_item_error.tsx create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_generic_errors_list.tsx create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 7b7c57ff4f7f25..413e8905bea93b 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -360,6 +360,10 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { macos_system_ext: `${SECURITY_SOLUTION_DOCS}deploy-elastic-endpoint.html#system-extension-endpoint`, linux_deadlock: `${SECURITY_SOLUTION_DOCS}ts-management.html#linux-deadlock`, }, + packageActionTroubleshooting: { + // TODO: Pending to be updated when docs are ready + es_connection: '', + }, responseActions: `${SECURITY_SOLUTION_DOCS}response-actions.html`, }, query: { diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index fb934f4aa4f2ab..1ee0d5414b2753 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -264,6 +264,9 @@ export interface DocLinks { macos_system_ext: string; linux_deadlock: string; }; + readonly packageActionTroubleshooting: { + es_connection: string; + }; readonly threatIntelInt: string; readonly responseActions: string; }; diff --git a/x-pack/plugins/fleet/common/types/models/agent.ts b/x-pack/plugins/fleet/common/types/models/agent.ts index 7b92e6e779fd51..0bc0ddb22d150c 100644 --- a/x-pack/plugins/fleet/common/types/models/agent.ts +++ b/x-pack/plugins/fleet/common/types/models/agent.ts @@ -81,6 +81,7 @@ interface AgentBase { user_provided_metadata: AgentMetadata; local_metadata: AgentMetadata; tags?: string[]; + components?: FleetServerAgentComponent[]; } export interface Agent extends AgentBase { @@ -121,7 +122,7 @@ export interface ActionStatus { } // Generated from FleetServer schema.json -interface FleetServerAgentComponentUnit { +export interface FleetServerAgentComponentUnit { id: string; type: 'input' | 'output'; status: FleetServerAgentComponentStatus; diff --git a/x-pack/plugins/fleet/dev_docs/fleet_ui_extensions.md b/x-pack/plugins/fleet/dev_docs/fleet_ui_extensions.md index 32486a8db3df59..9dcb7112f7ef08 100644 --- a/x-pack/plugins/fleet/dev_docs/fleet_ui_extensions.md +++ b/x-pack/plugins/fleet/dev_docs/fleet_ui_extensions.md @@ -44,6 +44,12 @@ export class Plugin { view: 'package-policy-response', Component: getLazyEndpointPolicyResponseExtension(core, plugins), }); + + registerExtension({ + package: 'endpoint', + view: 'package-generic-errors-list', + Component: getLazyEndpointGenericErrorsListExtension(core, plugins), + }); } //... } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_integrations.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_integrations.tsx index 2e238d4142f1de..dbe58b252a707e 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_integrations.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_integrations.tsx @@ -20,11 +20,13 @@ import { EuiBadge, useEuiTheme, } from '@elastic/eui'; +import { filter } from 'lodash'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import styled from 'styled-components'; import type { Agent, AgentPolicy, PackagePolicy } from '../../../../../types'; +import type { FleetServerAgentComponentUnit } from '../../../../../../../../common/types/models/agent'; import { useLink, useUIExtension } from '../../../../../hooks'; import { ExtensionWrapper, PackageIcon } from '../../../../../components'; @@ -94,11 +96,16 @@ export const AgentDetailsIntegration: React.FunctionComponent<{ const { getHref } = useLink(); const theme = useEuiTheme(); - const [showNeedsAttentionBadge, setShowNeedsAttentionBadge] = useState(false); + const [isAttentionBadgeNeededForPolicyResponse, setIsAttentionBadgeNeededForPolicyResponse] = + useState(false); const extensionView = useUIExtension( packagePolicy.package?.name ?? '', 'package-policy-response' ); + const genericErrorsListExtensionView = useUIExtension( + packagePolicy.package?.name ?? '', + 'package-generic-errors-list' + ); const policyResponseExtensionView = useMemo(() => { return ( @@ -106,13 +113,41 @@ export const AgentDetailsIntegration: React.FunctionComponent<{ <ExtensionWrapper> <extensionView.Component agent={agent} - onShowNeedsAttentionBadge={setShowNeedsAttentionBadge} + onShowNeedsAttentionBadge={setIsAttentionBadgeNeededForPolicyResponse} /> </ExtensionWrapper> ) ); }, [agent, extensionView]); + const packageErrors = useMemo(() => { + const packageErrorUnits: FleetServerAgentComponentUnit[] = []; + if (!agent.components) { + return packageErrorUnits; + } + + const filteredPackageComponents = filter(agent.components, { + type: packagePolicy.package?.name, + }); + + filteredPackageComponents.forEach((component) => { + packageErrorUnits.push(...filter(component.units, { status: 'failed' })); + }); + return packageErrorUnits; + }, [agent.components, packagePolicy]); + + const showNeedsAttentionBadge = isAttentionBadgeNeededForPolicyResponse || packageErrors.length; + + const genericErrorsListExtensionViewWrapper = useMemo(() => { + return ( + genericErrorsListExtensionView && ( + <ExtensionWrapper> + <genericErrorsListExtensionView.Component packageErrors={packageErrors} /> + </ExtensionWrapper> + ) + ); + }, [packageErrors, genericErrorsListExtensionView]); + const inputItems = [ { label: ( @@ -217,6 +252,7 @@ export const AgentDetailsIntegration: React.FunctionComponent<{ aria-labelledby="inputsTreeView" /> {policyResponseExtensionView} + {genericErrorsListExtensionViewWrapper} <EuiSpacer /> </CollapsablePanel> ); diff --git a/x-pack/plugins/fleet/public/index.ts b/x-pack/plugins/fleet/public/index.ts index d510d57c522573..a55937999c4d66 100644 --- a/x-pack/plugins/fleet/public/index.ts +++ b/x-pack/plugins/fleet/public/index.ts @@ -42,6 +42,8 @@ export type { PackagePolicyResponseExtension, PackagePolicyResponseExtensionComponent, PackagePolicyResponseExtensionComponentProps, + PackageGenericErrorsListProps, + PackageGenericErrorsListComponent, UIExtensionPoint, UIExtensionRegistrationCallback, UIExtensionsStorage, diff --git a/x-pack/plugins/fleet/public/types/ui_extensions.ts b/x-pack/plugins/fleet/public/types/ui_extensions.ts index 17e9a25c656d05..c3a9f05fc7d9fc 100644 --- a/x-pack/plugins/fleet/public/types/ui_extensions.ts +++ b/x-pack/plugins/fleet/public/types/ui_extensions.ts @@ -8,6 +8,8 @@ import type { EuiStepProps } from '@elastic/eui'; import type { ComponentType, LazyExoticComponent } from 'react'; +import type { FleetServerAgentComponentUnit } from '../../common/types/models/agent'; + import type { Agent, NewPackagePolicy, PackageInfo, PackagePolicy } from '.'; /** Register a Fleet UI extension */ @@ -60,6 +62,17 @@ export interface PackagePolicyResponseExtensionComponentProps { onShowNeedsAttentionBadge?: (val: boolean) => void; } +/** + * UI Component Extension is used on the pages displaying the ability to see + * a generic endpoint errors list + */ +export type PackageGenericErrorsListComponent = ComponentType<PackageGenericErrorsListProps>; + +export interface PackageGenericErrorsListProps { + /** A list of errors from a package */ + packageErrors: FleetServerAgentComponentUnit[]; +} + /** Extension point registration contract for Integration Policy Edit views */ export interface PackagePolicyEditExtension { package: string; @@ -74,6 +87,12 @@ export interface PackagePolicyResponseExtension { Component: LazyExoticComponent<PackagePolicyResponseExtensionComponent>; } +export interface PackageGenericErrorsListExtension { + package: string; + view: 'package-generic-errors-list'; + Component: LazyExoticComponent<PackageGenericErrorsListComponent>; +} + /** Extension point registration contract for Integration Policy Edit tabs views */ export interface PackagePolicyEditTabsExtension { package: string; @@ -158,4 +177,5 @@ export type UIExtensionPoint = | PackageCustomExtension | PackagePolicyCreateExtension | PackageAssetsExtension + | PackageGenericErrorsListExtension | AgentEnrollmentFlyoutFinalStepExtension; diff --git a/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts new file mode 100644 index 00000000000000..57117c9b1397c9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts @@ -0,0 +1,81 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import type { DocLinks } from '@kbn/doc-links'; + +type PackageActions = 'es_connection'; + +export const titles = Object.freeze( + new Map<PackageActions, string>([ + [ + 'es_connection', + i18n.translate('xpack.securitySolution.endpoint.details.packageActions.es_connection.title', { + defaultMessage: 'Elasticsearch connection failure', + }), + ], + ]) +); + +export const descriptions = Object.freeze( + new Map<Partial<PackageActions> | string, string>([ + [ + 'es_connection', + i18n.translate( + 'xpack.securitySolution.endpoint.details.packageActions.es_connection.description', + { + defaultMessage: + "The endpoint's connection to Elasticsearch is either down or misconfigured. Make sure it is configured correctly.", + } + ), + ], + ]) +); + +const linkTexts = Object.freeze( + new Map<Partial<PackageActions> | string, string>([ + [ + 'es_connection', + i18n.translate( + 'xpack.securitySolution.endpoint.details.packageActions.link.text.es_connection', + { + defaultMessage: ' Read more.', + } + ), + ], + ]) +); + +export class PackageActionFormatter { + public key: PackageActions; + public title: string; + public description: string; + public linkText?: string; + + constructor( + code: number, + message: string, + private docLinks: DocLinks['securitySolution']['packageActionTroubleshooting'] + ) { + this.key = this.getKeyFromErrorCode(code); + this.title = titles.get(this.key) ?? this.key; + this.description = descriptions.get(this.key) || message; + this.linkText = linkTexts.get(this.key); + } + + public get linkUrl(): string { + return this.docLinks[this.key]; + } + + private getKeyFromErrorCode(code: number): PackageActions { + if (code === 123) { + return 'es_connection'; + } else { + throw new Error(`Invalid error code ${code}`); + } + } +} diff --git a/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_item_error.tsx b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_item_error.tsx new file mode 100644 index 00000000000000..63e3c2d5488399 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_item_error.tsx @@ -0,0 +1,53 @@ +/* + * 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, { memo } from 'react'; +import styled from 'styled-components'; +import { EuiLink, EuiCallOut, EuiText } from '@elastic/eui'; +import type { PackageActionFormatter } from './package_action_formatter'; + +const StyledEuiCallout = styled(EuiCallOut)` + padding: ${({ theme }) => theme.eui.euiSizeS}; +`; + +const StyledEuiText = styled(EuiText)` + white-space: break-spaces; + text-align: left; + line-height: inherit; +`; + +interface PackageActionItemErrorProps { + actionFormatter: PackageActionFormatter; +} +/** + * A package action item error + */ +export const PackageActionItemError = memo(({ actionFormatter }: PackageActionItemErrorProps) => { + return ( + <StyledEuiCallout + title={actionFormatter.title} + color="danger" + iconType="alert" + data-test-subj="packageItemErrorCallOut" + > + <StyledEuiText size="s" data-test-subj="packageItemErrorCallOutMessage"> + {actionFormatter.description} + {actionFormatter.linkText && actionFormatter.linkUrl && ( + <EuiLink + target="_blank" + href={actionFormatter.linkUrl} + data-test-subj="packageItemErrorCallOutLink" + > + {actionFormatter.linkText} + </EuiLink> + )} + </StyledEuiText> + </StyledEuiCallout> + ); +}); + +PackageActionItemError.displayName = 'PackageActionItemError'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_generic_errors_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_generic_errors_list.tsx new file mode 100644 index 00000000000000..cac9c2a7d0c2ce --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_generic_errors_list.tsx @@ -0,0 +1,52 @@ +/* + * 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, { memo, useMemo } from 'react'; +import type { PackageGenericErrorsListProps } from '@kbn/fleet-plugin/public'; +import { EuiSpacer } from '@elastic/eui'; + +import { useKibana } from '../../../../../common/lib/kibana'; +import { PackageActionFormatter } from '../../../../components/package_action_item/package_action_formatter'; +import { PackageActionItemError } from '../../../../components/package_action_item/package_action_item_error'; + +/** + * Exports Endpoint-generic errors list + */ +export const EndpointGenericErrorsList = memo<PackageGenericErrorsListProps>( + ({ packageErrors }) => { + const { docLinks } = useKibana().services; + + const globalEndpointErrors = useMemo(() => { + const errors: PackageActionFormatter[] = []; + packageErrors.forEach((unit) => { + if (unit.payload && unit.payload.error) { + errors.push( + new PackageActionFormatter( + unit.payload.error.code, + unit.payload.error.message, + docLinks.links.securitySolution.packageActionTroubleshooting + ) + ); + } + }); + + return errors; + }, [packageErrors, docLinks.links.securitySolution.packageActionTroubleshooting]); + + return ( + <> + {globalEndpointErrors.map((error) => ( + <React.Fragment key={error.key}> + <PackageActionItemError actionFormatter={error} /> + <EuiSpacer size="m" /> + </React.Fragment> + ))} + </> + ); + } +); +EndpointGenericErrorsList.displayName = 'EndpointGenericErrorsList'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx new file mode 100644 index 00000000000000..1d753bb4f1a262 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list.tsx @@ -0,0 +1,34 @@ +/* + * 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 { lazy } from 'react'; +import type { CoreStart } from '@kbn/core/public'; +import type { + PackageGenericErrorsListComponent, + PackageGenericErrorsListProps, +} from '@kbn/fleet-plugin/public'; +import type { StartPlugins } from '../../../../../types'; + +export const getLazyEndpointGenericErrorsListExtension = ( + coreStart: CoreStart, + depsStart: Pick<StartPlugins, 'data' | 'fleet'> +) => { + return lazy<PackageGenericErrorsListComponent>(async () => { + const [{ withSecurityContext }, { EndpointGenericErrorsList }] = await Promise.all([ + import('./with_security_context/with_security_context'), + import('./endpoint_generic_errors_list'), + ]); + + return { + default: withSecurityContext<PackageGenericErrorsListProps>({ + coreStart, + depsStart, + WrappedComponent: EndpointGenericErrorsList, + }), + }; + }); +}; diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 490a68922b176b..7affdd066742f0 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -62,6 +62,7 @@ import { getLazyEndpointPolicyEditExtension } from './management/pages/policy/vi import { LazyEndpointPolicyCreateExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_create_extension'; import { getLazyEndpointPackageCustomExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_package_custom_extension'; import { getLazyEndpointPolicyResponseExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_policy_response_extension'; +import { getLazyEndpointGenericErrorsListExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_generic_errors_list'; import type { ExperimentalFeatures } from '../common/experimental_features'; import { parseExperimentalConfigValue } from '../common/experimental_features'; import { LazyEndpointCustomAssetsExtension } from './management/pages/policy/view/ingest_manager_integration/lazy_endpoint_custom_assets_extension'; @@ -232,6 +233,11 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S view: 'package-policy-response', Component: getLazyEndpointPolicyResponseExtension(core, plugins), }); + registerExtension({ + package: 'endpoint', + view: 'package-generic-errors-list', + Component: getLazyEndpointGenericErrorsListExtension(core, plugins), + }); } registerExtension({ From 06360d3402a0ed4e76d9edaf74f7bb01b121b575 Mon Sep 17 00:00:00 2001 From: Joe Reuter <johannes.reuter@elastic.co> Date: Tue, 13 Sep 2022 10:53:22 +0200 Subject: [PATCH 097/144] format boolean values correctly by default (#140308) --- .../public/application/components/lib/create_field_formatter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/create_field_formatter.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/create_field_formatter.ts index 0dc709e786c8bc..16ae8372301ed0 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/create_field_formatter.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/create_field_formatter.ts @@ -33,6 +33,8 @@ export const createFieldFormatter = ( ? { id: 'date' } : fieldType === 'string' ? { id: 'string' } + : fieldType === 'boolean' + ? { id: 'boolean' } : { id: 'number' }; const fieldFormat = getFieldFormats().deserialize( From 82217146edc17f06fbedef0b5041f35c5eff16b9 Mon Sep 17 00:00:00 2001 From: Joe Reuter <johannes.reuter@elastic.co> Date: Tue, 13 Sep 2022 10:54:21 +0200 Subject: [PATCH 098/144] show metric name if there are multiple layers with breakdowns (#140314) --- .../public/components/data_layers.tsx | 3 +++ .../public/components/legend_action.tsx | 2 ++ .../public/components/legend_color_picker.tsx | 2 ++ .../public/helpers/color_assignment.ts | 16 ++++++++++++---- .../expression_xy/public/helpers/data_layers.tsx | 14 ++++++++++++-- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx index 035faf8d22b003..7cf772ff7dd542 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/data_layers.tsx @@ -33,6 +33,7 @@ import { DatatablesWithFormatInfo, LayersAccessorsTitles, LayersFieldFormats, + hasMultipleLayersWithSplits, } from '../helpers'; interface Props { @@ -108,6 +109,7 @@ export const DataLayers: FC<Props> = ({ { commonLayerId: formattedDatatables[layers[0].layerId] } ) : getColorAssignments(layers, titles, fieldFormats, formattedDatatables); + const multipleLayersWithSplits = hasMultipleLayersWithSplits(layers); return ( <> {layers.flatMap((layer) => { @@ -163,6 +165,7 @@ export const DataLayers: FC<Props> = ({ uiState, allYAccessors, singleTable, + multipleLayersWithSplits, }); const index = `${layer.layerId}-${accessorIndex}`; diff --git a/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx b/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx index 0d1d3b5b592569..37789a6ffa15e3 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/legend_action.tsx @@ -15,6 +15,7 @@ import { LegendActionPopover } from './legend_action_popover'; import { DatatablesWithFormatInfo, getSeriesName, + hasMultipleLayersWithSplits, LayersAccessorsTitles, LayersFieldFormats, } from '../helpers'; @@ -85,6 +86,7 @@ export const getLegendAction = ( splitAccessorsFormats: fieldFormats[layer.layerId].splitSeriesAccessors, alreadyFormattedColumns: formattedDatatables[layer.layerId].formattedColumns, columnToLabelMap: layer.columnToLabel ? JSON.parse(layer.columnToLabel) : {}, + multipleLayersWithSplits: hasMultipleLayersWithSplits(dataLayers), }, titles )?.toString() || '' diff --git a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx index 3573fc65e52884..7ae16b9c6f05a1 100644 --- a/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/components/legend_color_picker.tsx @@ -15,6 +15,7 @@ import { DatatablesWithFormatInfo, getMetaFromSeriesId, getSeriesName, + hasMultipleLayersWithSplits, LayersAccessorsTitles, LayersFieldFormats, } from '../helpers'; @@ -90,6 +91,7 @@ export const LegendColorPickerWrapper: LegendColorPicker = ({ splitAccessorsFormats: fieldFormats[layer.layerId].splitSeriesAccessors, alreadyFormattedColumns: formattedDatatables[layer.layerId].formattedColumns, columnToLabelMap: layer.columnToLabel ? JSON.parse(layer.columnToLabel) : {}, + multipleLayersWithSplits: hasMultipleLayersWithSplits(dataLayers), }, titles[layer.layerId] )?.toString() || '' diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts index 2cce918d4b7984..94b187055e6dd7 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/color_assignment.ts @@ -19,7 +19,11 @@ import { LayersAccessorsTitles, LayersFieldFormats, } from './layers'; -import { DatatablesWithFormatInfo, DatatableWithFormatInfo } from './data_layers'; +import { + DatatablesWithFormatInfo, + DatatableWithFormatInfo, + hasMultipleLayersWithSplits, +} from './data_layers'; export const defaultReferenceLineColor = euiLightVars.euiColorDarkShade; @@ -59,7 +63,8 @@ export const getAllSeries = ( columnToLabel: CommonXYDataLayerConfig['columnToLabel'], titles: LayerAccessorsTitles, fieldFormats: LayerFieldFormats, - accessorsCount: number + accessorsCount: number, + multipleLayersWithSplits: boolean ) => { if (!formattedDatatable.table) { return []; @@ -77,7 +82,8 @@ export const getAllSeries = ( const yTitle = columnToLabelMap[yAccessor] ?? titles?.yTitles?.[yAccessor] ?? null; let name = yTitle; if (splitName) { - name = accessorsCount > 1 ? `${splitName} - ${yTitle}` : splitName; + name = + accessorsCount > 1 || multipleLayersWithSplits ? `${splitName} - ${yTitle}` : splitName; } if (!allSeries.includes(name)) { @@ -108,6 +114,7 @@ export function getColorAssignments( } layersPerPalette[palette].push(layer); }); + const multipleLayersWithSplits = hasMultipleLayersWithSplits(layers); return mapValues(layersPerPalette, (paletteLayers) => { const seriesPerLayer = paletteLayers.map((layer) => { @@ -119,7 +126,8 @@ export function getColorAssignments( layer.columnToLabel, titles[layer.layerId], fieldFormats[layer.layerId], - layer.accessors.length + layer.accessors.length, + multipleLayersWithSplits ) || []; return { numberOfSeries: allSeries.length, allSeries }; diff --git a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx index 8098bb0efe02b2..7476d43f773e8b 100644 --- a/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/helpers/data_layers.tsx @@ -24,7 +24,8 @@ import { Datatable } from '@kbn/expressions-plugin/common'; import { getAccessorByDimension } from '@kbn/visualizations-plugin/common/utils'; import type { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common/expression_functions'; import { PaletteRegistry, SeriesLayer } from '@kbn/coloring'; -import { CommonXYDataLayerConfig, XScaleType } from '../../common'; +import { isDataLayer } from '../../common/utils/layer_types_guards'; +import { CommonXYDataLayerConfig, CommonXYLayerConfig, XScaleType } from '../../common'; import { AxisModes, SeriesTypes } from '../../common/constants'; import { FormatFactory } from '../types'; import { getSeriesColor } from './state'; @@ -55,6 +56,7 @@ type GetSeriesPropsFn = (config: { uiState?: PersistedState; allYAccessors: Array<string | ExpressionValueVisDimension>; singleTable?: boolean; + multipleLayersWithSplits: boolean; }) => SeriesSpec; type GetSeriesNameFn = ( @@ -66,6 +68,7 @@ type GetSeriesNameFn = ( splitAccessorsFormats: LayerFieldFormats['splitSeriesAccessors']; alreadyFormattedColumns: Record<string, boolean>; columnToLabelMap: Record<string, string>; + multipleLayersWithSplits: boolean; }, titles: LayerAccessorsTitles ) => SeriesName; @@ -254,6 +257,7 @@ export const getSeriesName: GetSeriesNameFn = ( splitAccessorsFormats, alreadyFormattedColumns, columnToLabelMap, + multipleLayersWithSplits, }, titles ) => { @@ -272,7 +276,7 @@ export const getSeriesName: GetSeriesNameFn = ( const key = data.seriesKeys[data.seriesKeys.length - 1]; const yAccessorTitle = columnToLabelMap[key] ?? titles?.yTitles?.[key] ?? null; - if (accessorsCount > 1) { + if (accessorsCount > 1 || multipleLayersWithSplits) { if (splitValues.length === 0) { return yAccessorTitle; } @@ -369,6 +373,10 @@ export const getMetaFromSeriesId = (seriesId: string) => { }; }; +export function hasMultipleLayersWithSplits(layers: CommonXYLayerConfig[]) { + return layers.filter((l) => isDataLayer(l) && (l.splitAccessors?.length || 0) > 0).length > 1; +} + export const getSeriesProps: GetSeriesPropsFn = ({ layer, titles = {}, @@ -389,6 +397,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ uiState, allYAccessors, singleTable, + multipleLayersWithSplits, }): SeriesSpec => { const { table, isStacked, markSizeAccessor } = layer; const isPercentage = layer.isPercentage; @@ -464,6 +473,7 @@ export const getSeriesProps: GetSeriesPropsFn = ({ columns: formattedTable.columns, splitAccessorsFormats: fieldFormats[layer.layerId].splitSeriesAccessors, columnToLabelMap, + multipleLayersWithSplits, }, titles ); From 886d61ae72cdd7e9421f6a9fce2d6dbb0a17663e Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin <aleh.zasypkin@elastic.co> Date: Tue, 13 Sep 2022 11:13:21 +0200 Subject: [PATCH 099/144] Get rid of `esArchiver` in the `Copy To Spaces` integration tests. (#137831) --- x-pack/test/common/services/spaces.ts | 15 + .../apps/spaces/copy_saved_objects.ts | 24 +- .../spaces/copy_saved_objects/data.json | 171 --------- .../spaces/copy_saved_objects/mappings.json | 293 ---------------- .../copy_saved_objects_default_space.json | 134 +++++++ .../copy_saved_objects_sales_space.json | 17 + .../spaces_api_integration/common/config.ts | 1 + .../fixtures/kbn_archiver/default_space.json | 330 ++++++++++++++++++ .../common/fixtures/kbn_archiver/space_1.json | 197 +++++++++++ .../common/fixtures/kbn_archiver/space_2.json | 74 ++++ .../common/lib/test_data_loader.ts | 128 +++++++ .../common/suites/copy_to_space.ts | 75 ++-- .../security_and_spaces/apis/copy_to_space.ts | 11 +- .../spaces_only/apis/copy_to_space.ts | 10 +- 14 files changed, 958 insertions(+), 522 deletions(-) delete mode 100644 x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json delete mode 100644 x-pack/test/functional/es_archives/spaces/copy_saved_objects/mappings.json create mode 100644 x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_default_space.json create mode 100644 x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_sales_space.json create mode 100644 x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/default_space.json create mode 100644 x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_1.json create mode 100644 x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_2.json create mode 100644 x-pack/test/spaces_api_integration/common/lib/test_data_loader.ts diff --git a/x-pack/test/common/services/spaces.ts b/x-pack/test/common/services/spaces.ts index bae83a71d3c279..ad829e45fccecf 100644 --- a/x-pack/test/common/services/spaces.ts +++ b/x-pack/test/common/services/spaces.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type { Space } from '@kbn/spaces-plugin/common'; import Axios from 'axios'; import { format as formatUrl } from 'url'; import util from 'util'; @@ -46,5 +47,19 @@ export function SpacesServiceProvider({ getService }: FtrProviderContext) { } log.debug(`deleted space id: ${spaceId}`); } + + public async getAll() { + log.debug('retrieving all spaces'); + const { data, status, statusText } = await axios.get<Space[]>('/api/spaces/space'); + + if (status !== 200) { + throw new Error( + `Expected status code of 200, received ${status} ${statusText}: ${util.inspect(data)}` + ); + } + log.debug(`retrieved ${data.length} spaces`); + + return data; + } })(); } diff --git a/x-pack/test/functional/apps/spaces/copy_saved_objects.ts b/x-pack/test/functional/apps/spaces/copy_saved_objects.ts index 2d2fdf61a94b68..6260d2941956bf 100644 --- a/x-pack/test/functional/apps/spaces/copy_saved_objects.ts +++ b/x-pack/test/functional/apps/spaces/copy_saved_objects.ts @@ -8,18 +8,28 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; -export default function spaceSelectorFunctonalTests({ +export default function spaceSelectorFunctionalTests({ getService, getPageObjects, }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); + const kbnServer = getService('kibanaServer'); const spaces = getService('spaces'); const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['security', 'settings', 'copySavedObjectsToSpace']); + const log = getService('log'); describe('Copy Saved Objects to Space', function () { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/spaces/copy_saved_objects'); + log.debug('Loading test data for the following spaces: default, sales'); + await Promise.all([ + kbnServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_default_space.json' + ), + kbnServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_sales_space.json', + { space: 'sales' } + ), + ]); await spaces.create({ id: 'marketing', @@ -43,9 +53,15 @@ export default function spaceSelectorFunctonalTests({ }); after(async () => { + log.debug('Removing data from the following spaces: default, sales'); + await Promise.all( + ['default', 'sales'].map((spaceId) => + kbnServer.savedObjects.cleanStandardList({ space: spaceId }) + ) + ); + await spaces.delete('sales'); await spaces.delete('marketing'); - await esArchiver.unload('x-pack/test/functional/es_archives/spaces/copy_saved_objects'); }); it('allows a dashboard to be copied to the marketing space, with all references', async () => { diff --git a/x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json b/x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json deleted file mode 100644 index 552142d3b190ae..00000000000000 --- a/x-pack/test/functional/es_archives/spaces/copy_saved_objects/data.json +++ /dev/null @@ -1,171 +0,0 @@ -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "space:default", - "source": { - "space": { - "name": "Default", - "description": "This is the default space!", - "disabledFeatures": [], - "_reserved": true - }, - "type": "space", - "migrationVersion": { - "space": "6.6.0" - } - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "index-pattern:logstash-*", - "source": { - "index-pattern": { - "title": "logstash-*", - "timeFieldName": "@timestamp", - "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]" - }, - "type": "index-pattern", - "migrationVersion": { - "index-pattern": "6.5.0" - }, - "updated_at": "2018-12-21T00:43:07.096Z" - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "sales:index-pattern:logstash-*", - "source": { - "namespace": "sales", - "index-pattern": { - "title": "logstash-*", - "timeFieldName": "@timestamp", - "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]" - }, - "type": "index-pattern", - "migrationVersion": { - "index-pattern": "6.5.0" - }, - "updated_at": "2018-12-21T00:43:07.096Z" - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "visualization:75c3e060-1e7c-11e9-8488-65449e65d0ed", - "source": { - "visualization": { - "title": "A Pie", - "visState": "{\"title\":\"A Pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":0,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}", - "uiStateJSON": "{}", - "description": "", - "version": 1, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" - } - }, - "type": "visualization", - "updated_at": "2019-01-22T19:32:31.206Z" - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "dashboard:my-dashboard", - "source": { - "dashboard": { - "title": "A Dashboard", - "hits": 0, - "description": "", - "panelsJSON": "[{\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"version\":\"7.0.0\",\"panelIndex\":\"1\",\"type\":\"visualization\",\"id\":\"75c3e060-1e7c-11e9-8488-65449e65d0ed\",\"embeddableConfig\":{}}]", - "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}", - "version": 1, - "timeRestore": false, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" - } - }, - "type": "dashboard", - "updated_at": "2019-01-22T19:32:47.232Z" - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "dashboard:dashboard-foo", - "source": { - "references": [{ - "id":"dashboard-bar", - "name":"dashboard-circular-ref", - "type":"dashboard" - }], - "dashboard": { - "title": "Dashboard Foo", - "hits": 0, - "description": "", - "panelsJSON": "[]", - "optionsJSON": "{}", - "version": 1, - "timeRestore": false, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" - } - }, - "type": "dashboard", - "updated_at": "2019-01-22T19:32:47.232Z" - } - } -} - -{ - "type": "doc", - "value": { - "index": ".kibana", - "type": "doc", - "id": "dashboard:dashboard-bar", - "source": { - "references": [{ - "id":"dashboard-foo", - "name":"dashboard-circular-ref", - "type":"dashboard" - }], - "dashboard": { - "title": "Dashboard Bar", - "hits": 0, - "description": "", - "panelsJSON": "[]", - "optionsJSON": "{}", - "version": 1, - "timeRestore": false, - "kibanaSavedObjectMeta": { - "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" - } - }, - "type": "dashboard", - "updated_at": "2019-01-22T19:32:47.232Z" - } - } -} diff --git a/x-pack/test/functional/es_archives/spaces/copy_saved_objects/mappings.json b/x-pack/test/functional/es_archives/spaces/copy_saved_objects/mappings.json deleted file mode 100644 index 092f8a326d9dfd..00000000000000 --- a/x-pack/test/functional/es_archives/spaces/copy_saved_objects/mappings.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "type": "index", - "value": { - "aliases": { - ".kibana": {} - }, - "index": ".kibana_1", - "mappings": { - "dynamic": "strict", - "properties": { - "migrationVersion": { - "dynamic": "true", - "properties": { - "index-pattern": { - "type": "text", - "fields": { - "keyword": { - "type": "keyword", - "ignore_above": 256 - } - } - } - } - }, - "config": { - "dynamic": "true", - "properties": { - "buildNum": { - "type": "keyword" - }, - "dateFormat:tz": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "defaultIndex": { - "fields": { - "keyword": { - "ignore_above": 256, - "type": "keyword" - } - }, - "type": "text" - }, - "notifications:lifetime:banner": { - "type": "long" - }, - "notifications:lifetime:error": { - "type": "long" - }, - "notifications:lifetime:info": { - "type": "long" - }, - "notifications:lifetime:warning": { - "type": "long" - } - } - }, - "dashboard": { - "properties": { - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "optionsJSON": { - "type": "text" - }, - "panelsJSON": { - "type": "text" - }, - "refreshInterval": { - "properties": { - "display": { - "type": "keyword" - }, - "pause": { - "type": "boolean" - }, - "section": { - "type": "integer" - }, - "value": { - "type": "integer" - } - } - }, - "timeFrom": { - "type": "keyword" - }, - "timeRestore": { - "type": "boolean" - }, - "timeTo": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "index-pattern": { - "properties": { - "fieldFormatMap": { - "type": "text" - }, - "fields": { - "type": "text" - }, - "intervalName": { - "type": "keyword" - }, - "notExpandable": { - "type": "boolean" - }, - "sourceFilters": { - "type": "text" - }, - "timeFieldName": { - "type": "keyword" - }, - "title": { - "type": "text" - } - } - }, - "search": { - "properties": { - "columns": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "hits": { - "type": "integer" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "sort": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "version": { - "type": "integer" - } - } - }, - "server": { - "properties": { - "uuid": { - "type": "keyword" - } - } - }, - "type": { - "type": "keyword" - }, - "updated_at": { - "type": "date" - }, - "url": { - "properties": { - "accessCount": { - "type": "long" - }, - "accessDate": { - "type": "date" - }, - "createDate": { - "type": "date" - }, - "url": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "visualization": { - "properties": { - "description": { - "type": "text" - }, - "kibanaSavedObjectMeta": { - "properties": { - "searchSourceJSON": { - "type": "text" - } - } - }, - "savedSearchId": { - "type": "keyword" - }, - "title": { - "type": "text" - }, - "uiStateJSON": { - "type": "text" - }, - "version": { - "type": "integer" - }, - "visState": { - "type": "text" - } - } - }, - "namespace": { - "type": "keyword" - }, - "space": { - "properties": { - "_reserved": { - "type": "boolean" - }, - "color": { - "type": "keyword" - }, - "description": { - "type": "text" - }, - "disabledFeatures": { - "type": "keyword" - }, - "initials": { - "type": "keyword" - }, - "name": { - "fields": { - "keyword": { - "ignore_above": 2048, - "type": "keyword" - } - }, - "type": "text" - } - } - }, - "references": { - "type": "nested", - "properties": { - "name": { - "type": "keyword" - }, - "type": { - "type": "keyword" - }, - "id": { - "type": "keyword" - } - } - } - } - }, - "settings": { - "index": { - "auto_expand_replicas": "0-1", - "number_of_replicas": "0", - "number_of_shards": "1" - } - } - } -} \ No newline at end of file diff --git a/x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_default_space.json b/x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_default_space.json new file mode 100644 index 00000000000000..a86e88d114e7fe --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_default_space.json @@ -0,0 +1,134 @@ +{ + "attributes": { + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "8.5.0", + "id": "logstash-*", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2018-12-21T00:43:07.096Z", + "version": "WzksMl0=" +} + +{ + "attributes": { + "description": "", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}" + }, + "title": "A Pie", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"A Pie\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":0,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"}},\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"distinctColors\":true,\"legendDisplay\":\"show\",\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.src\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}" + }, + "coreMigrationVersion": "8.5.0", + "id": "75c3e060-1e7c-11e9-8488-65449e65d0ed", + "migrationVersion": { + "visualization": "8.5.0" + }, + "references": [ + { + "id": "logstash-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2019-01-22T19:32:31.206Z", + "version": "WzEyLDJd" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "optionsJSON": "{\"darkTheme\":false,\"useMargins\":true,\"hidePanelTitles\":false}", + "panelsJSON": "[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"w\":24,\"h\":15,\"x\":0,\"y\":0,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"}]", + "timeRestore": false, + "title": "A Dashboard", + "version": 1 + }, + "coreMigrationVersion": "8.5.0", + "id": "my-dashboard", + "migrationVersion": { + "dashboard": "8.5.0" + }, + "references": [ + { + "id": "75c3e060-1e7c-11e9-8488-65449e65d0ed", + "name": "1:panel_1", + "type": "visualization" + } + ], + "type": "dashboard", + "updated_at": "2019-01-22T19:32:47.232Z", + "version": "WzEzLDJd" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "optionsJSON": "{}", + "panelsJSON": "[]", + "timeRestore": false, + "title": "Dashboard Bar", + "version": 1 + }, + "coreMigrationVersion": "8.5.0", + "id": "dashboard-bar", + "migrationVersion": { + "dashboard": "8.5.0" + }, + "references": [ + { + "id": "dashboard-foo", + "name": "dashboard-circular-ref", + "type": "dashboard" + } + ], + "type": "dashboard", + "updated_at": "2019-01-22T19:32:47.232Z", + "version": "WzE1LDJd" +} + +{ + "attributes": { + "description": "", + "hits": 0, + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}" + }, + "optionsJSON": "{}", + "panelsJSON": "[]", + "timeRestore": false, + "title": "Dashboard Foo", + "version": 1 + }, + "coreMigrationVersion": "8.5.0", + "id": "dashboard-foo", + "migrationVersion": { + "dashboard": "8.5.0" + }, + "references": [ + { + "id": "dashboard-bar", + "name": "dashboard-circular-ref", + "type": "dashboard" + } + ], + "type": "dashboard", + "updated_at": "2019-01-22T19:32:47.232Z", + "version": "WzE0LDJd" +} diff --git a/x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_sales_space.json b/x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_sales_space.json new file mode 100644 index 00000000000000..b5505aab8c3b0d --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/spaces/copy_saved_objects_sales_space.json @@ -0,0 +1,17 @@ +{ + "attributes": { + "fields": "[{\"name\":\"@message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@message.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@tags\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@tags.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"agent.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"clientip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"extension.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.coordinates\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.dest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.src\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"geo.srcdest\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"headings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"headings.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"host.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"index.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"links\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"links.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.os\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"machine.os.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"machine.ram\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"memory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.char\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"meta.related\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.firstname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"meta.user.lastname\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"phpmemory\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"referer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:modified_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:published_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:section\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:section.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.article:tag\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.article:tag.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:height\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:height.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:image:width\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:image:width.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:site_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:site_name.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:type.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.og:url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.og:url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:card\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:card.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:description.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:image\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:image.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:site\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:site.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.twitter:title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.twitter:title.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"relatedContent.url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"relatedContent.url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"request\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"request.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"response.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"spaces\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"spaces.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"url\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"url.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"utc_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"xss\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"xss.raw\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]", + "timeFieldName": "@timestamp", + "title": "logstash-*" + }, + "coreMigrationVersion": "8.5.0", + "id": "fd534677-dd27-526a-bb03-37e3fbc9db5d", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "originId": "logstash-*", + "references": [], + "type": "index-pattern", + "updated_at": "2018-12-21T00:43:07.096Z", + "version": "WzEwLDJd" +} diff --git a/x-pack/test/spaces_api_integration/common/config.ts b/x-pack/test/spaces_api_integration/common/config.ts index 15a63fec6d309a..d7139e7bd1c343 100644 --- a/x-pack/test/spaces_api_integration/common/config.ts +++ b/x-pack/test/spaces_api_integration/common/config.ts @@ -41,6 +41,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) retry: config.xpack.api.get('services.retry'), esArchiver: config.kibana.functional.get('services.esArchiver'), kibanaServer: config.kibana.functional.get('services.kibanaServer'), + spaces: config.xpack.api.get('services.spaces'), }, junit: { reportName: 'X-Pack Spaces API Integration Tests -- ' + name, diff --git a/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/default_space.json b/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/default_space.json new file mode 100644 index 00000000000000..9179a846066f15 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/default_space.json @@ -0,0 +1,330 @@ +{ + "attributes": { + "title": "Copy to Space index pattern 1 from default space" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_ip_1_default", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "originId": "cts_ip_1", + "references": [], + "type": "index-pattern", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyOCwxXQ==" +} + +{ + "attributes": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "CTS vis 1 from default space", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_vis_1_default", + "migrationVersion": { + "visualization": "8.3.0" + }, + "references": [ + { + "id": "cts_ip_1_default", + "name": "CTS IP 1", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyMSwxXQ==" +} + +{ + "attributes": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "CTS vis 2 from default space", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_vis_2_default", + "migrationVersion": { + "visualization": "8.3.0" + }, + "references": [ + { + "id": "cts_ip_1_default", + "name": "CTS IP 1", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyMiwxXQ==" +} + +{ + "attributes": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "CTS vis 3 from default space", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_vis_3_default", + "migrationVersion": { + "visualization": "8.3.0" + }, + "originId": "cts_vis_3", + "references": [ + { + "id": "cts_ip_1_default", + "name": "CTS IP 1", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyMywxXQ==" +} + +{ + "attributes": { + "description": "Copy to Space Dashboard from the default space", + "title": "This is the default test space CTS dashboard" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_dashboard_default", + "migrationVersion": { + "dashboard": "8.4.0" + }, + "originId": "cts_dashboard", + "references": [ + { + "id": "cts_vis_1_default", + "name": "CTS Vis 1", + "type": "visualization" + }, + { + "id": "cts_vis_2_default", + "name": "CTS Vis 2", + "type": "visualization" + }, + { + "id": "cts_vis_3_default", + "name": "CTS Vis 3", + "type": "visualization" + } + ], + "type": "dashboard", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyMCwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in one space" + }, + "id": "conflict_2_default", + "originId": "conflict_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUxMCwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in all spaces" + }, + "id": "conflict_2_all", + "originId": "conflict_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUxMSwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an originId -> id match" + }, + "id": "conflict_1b_default", + "originId": "conflict_1b_space_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwMywxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an originId -> originId match" + }, + "id": "conflict_1a_default", + "originId": "conflict_1a", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwMCwxXQ==" +} + +{ + "attributes": { + "title": "Some title" + }, + "id": "my_isolated_object", + "references": [], + "type": "isolatedtype", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzQ4NywxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in all spaces" + }, + "id": "all_spaces", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5NywxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in one space" + }, + "id": "default_only", + "references": [ + { + "id": "each_space", + "name": "refname", + "type": "sharedtype" + } + ], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ4OCwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in the default, space_1, and space_2 spaces" + }, + "id": "each_space", + "references": [ + { + "id": "default_only", + "name": "refname", + "type": "sharedtype" + }, + { + "id": "space_1_only", + "name": "refname", + "type": "sharedtype" + }, + { + "id": "space_2_only", + "name": "refname", + "type": "sharedtype" + }, + { + "id": "all_spaces", + "name": "refname", + "type": "sharedtype" + } + ], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5NiwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an id -> originId match" + }, + "id": "conflict_1c_default_and_space_1", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwNiwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in the default and space_1 spaces" + }, + "id": "default_and_space_1", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5MywxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in the default and space_2 spaces" + }, + "id": "default_and_space_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5NCwxXQ==" +} + +{ + "attributes": { + "title": "This object only exists to test the third assertion for spacesWithMatchingOrigins in get_shareable_references" + }, + "id": "space_2_only_matching_origin", + "originId": "space_2_only", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5MiwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test that when an object is unshared from a space, inbound aliases for just those spaces are removed" + }, + "id": "alias_delete_inclusive", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5OCwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test that when an object is unshared from all space, inbound aliases for all spaces are removed" + }, + "id": "alias_delete_exclusive", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5OSwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in the space_1 and space_2 spaces" + }, + "id": "space_1_and_space_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5NSwxXQ==" +} diff --git a/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_1.json b/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_1.json new file mode 100644 index 00000000000000..d037b9d1bd24c5 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_1.json @@ -0,0 +1,197 @@ +{ + "attributes": { + "title": "Copy to Space index pattern 1 from space_1 space" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_ip_1_space_1", + "migrationVersion": { + "index-pattern": "8.0.0" + }, + "originId": "cts_ip_1", + "references": [], + "type": "index-pattern", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyOSwxXQ==" +} + +{ + "attributes": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "CTS vis 1 from space_1 space", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_vis_1_space_1", + "migrationVersion": { + "visualization": "8.3.0" + }, + "references": [ + { + "id": "cts_ip_1_space_1", + "name": "CTS IP 1", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyMSwxXQ==" +} + +{ + "attributes": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "CTS vis 2 from space_1 space", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_vis_2_space_1", + "migrationVersion": { + "visualization": "8.3.0" + }, + "references": [ + { + "id": "cts_ip_1_space_1", + "name": "CTS IP 1", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyNiwxXQ==" +} + +{ + "attributes": { + "description": "AreaChart", + "kibanaSavedObjectMeta": { + "searchSourceJSON": "{}" + }, + "title": "CTS vis 3 from space_1 space", + "uiStateJSON": "{}", + "version": 1, + "visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{},\"legendSize\":\"auto\"},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_vis_3_space_1", + "migrationVersion": { + "visualization": "8.3.0" + }, + "originId": "cts_vis_3", + "references": [ + { + "id": "cts_ip_1_space_1", + "name": "CTS IP 1", + "type": "index-pattern" + } + ], + "type": "visualization", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyNywxXQ==" +} + +{ + "attributes": { + "description": "Copy to Space Dashboard from space_1 space", + "title": "This is the space_1 test space CTS dashboard" + }, + "coreMigrationVersion": "8.4.0", + "id": "cts_dashboard_space_1", + "migrationVersion": { + "dashboard": "8.4.0" + }, + "originId": "cts_dashboard", + "references": [ + { + "id": "cts_vis_1_space_1", + "name": "CTS Vis 1", + "type": "visualization" + }, + { + "id": "cts_vis_2_space_1", + "name": "CTS Vis 2", + "type": "visualization" + }, + { + "id": "cts_vis_3_space_1", + "name": "CTS Vis 3", + "type": "visualization" + } + ], + "type": "dashboard", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzUyNCwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in one space" + }, + "id": "conflict_2_space_1", + "originId": "conflict_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUxMCwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an originId -> id match" + }, + "id": "conflict_1b_space_1", + "originId": "conflict_1b_space_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwNCwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an originId -> originId match" + }, + "id": "conflict_1a_space_1", + "originId": "conflict_1a", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwMSwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in one space" + }, + "id": "space_1_only", + "references": [ + { + "id": "each_space", + "name": "refname", + "type": "sharedtype" + } + ], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ4OSwxXQ==" +} + +{ + "attributes": { + "title": "Some title" + }, + "id": "my_isolated_object", + "references": [], + "type": "isolatedtype", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzQ4NywxXQ==" +} diff --git a/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_2.json b/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_2.json new file mode 100644 index 00000000000000..c68269eb1b3356 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_2.json @@ -0,0 +1,74 @@ +{ + "attributes": { + "title": "A shared saved-object in one space" + }, + "id": "conflict_2_space_2", + "originId": "conflict_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUxMCwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an id -> originId match" + }, + "id": "conflict_1c_space_2", + "originId": "conflict_1c_default_and_space_1", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwNywxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an originId -> id match" + }, + "id": "conflict_1b_space_2", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwNSwxXQ==" +} + +{ + "attributes": { + "title": "This is used to test an inexact match conflict for an originId -> originId match" + }, + "id": "conflict_1a_space_2", + "originId": "conflict_1a", + "references": [], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzUwMiwxXQ==" +} + +{ + "attributes": { + "title": "A shared saved-object in one space" + }, + "id": "space_2_only", + "references": [ + { + "id": "each_space", + "name": "refname", + "type": "sharedtype" + } + ], + "type": "sharedtype", + "updated_at": "2017-09-21T18:59:16.270Z", + "version": "WzQ5MSwxXQ==" +} + +{ + "attributes": { + "title": "Some title" + }, + "id": "my_isolated_object", + "references": [], + "type": "isolatedtype", + "updated_at": "2017-09-21T18:49:16.270Z", + "version": "WzQ4NywxXQ==" +} diff --git a/x-pack/test/spaces_api_integration/common/lib/test_data_loader.ts b/x-pack/test/spaces_api_integration/common/lib/test_data_loader.ts new file mode 100644 index 00000000000000..4b25c722603c87 --- /dev/null +++ b/x-pack/test/spaces_api_integration/common/lib/test_data_loader.ts @@ -0,0 +1,128 @@ +/* + * 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 { FtrProviderContext } from '../ftr_provider_context'; + +const SPACE_1 = { + id: 'space_1', + name: 'Space 1', + description: 'This is the first test space', + disabledFeatures: [], +}; + +const SPACE_2 = { + id: 'space_2', + name: 'Space 2', + description: 'This is the second test space', + disabledFeatures: [], +}; + +// Objects can only be imported in one space at a time. To have test saved objects +// that are shared in multiple spaces we should import all objects in the "original" +// spaces first and then share them to other spaces as a subsequent operation. +const OBJECTS_TO_SHARE: Array<{ + spacesToAdd?: string[]; + spacesToRemove?: string[]; + objects: Array<{ type: string; id: string }>; +}> = [ + { + spacesToAdd: ['*'], + spacesToRemove: ['default'], + objects: [ + { type: 'sharedtype', id: 'all_spaces' }, + { type: 'sharedtype', id: 'space_2_only_matching_origin' }, + { type: 'sharedtype', id: 'alias_delete_exclusive' }, + ], + }, + { + spacesToRemove: ['default'], + spacesToAdd: [SPACE_1.id, SPACE_2.id], + objects: [{ type: 'sharedtype', id: 'space_1_and_space_2' }], + }, + { + spacesToAdd: [SPACE_1.id, SPACE_2.id], + objects: [ + { type: 'sharedtype', id: 'each_space' }, + { type: 'sharedtype', id: 'conflict_2_all' }, + { type: 'sharedtype', id: 'alias_delete_inclusive' }, + ], + }, + { + spacesToAdd: [SPACE_1.id], + objects: [ + { type: 'sharedtype', id: 'conflict_1c_default_and_space_1' }, + { type: 'sharedtype', id: 'default_and_space_1' }, + ], + }, + { + spacesToAdd: [SPACE_2.id], + objects: [{ type: 'sharedtype', id: 'default_and_space_2' }], + }, +]; + +export function getTestDataLoader({ getService }: FtrProviderContext) { + const spacesService = getService('spaces'); + const kbnServer = getService('kibanaServer'); + const supertest = getService('supertest'); + const log = getService('log'); + + return { + before: async () => { + await Promise.all([await spacesService.create(SPACE_1), await spacesService.create(SPACE_2)]); + }, + + after: async () => { + await Promise.all([spacesService.delete(SPACE_1.id), spacesService.delete(SPACE_2.id)]); + }, + + beforeEach: async () => { + log.debug('Loading test data for the following spaces: default, space_1 and space_2'); + await Promise.all([ + kbnServer.importExport.load( + 'x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/default_space.json' + ), + kbnServer.importExport.load( + 'x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_1.json', + { space: SPACE_1.id } + ), + kbnServer.importExport.load( + 'x-pack/test/spaces_api_integration/common/fixtures/kbn_archiver/space_2.json', + { space: SPACE_2.id } + ), + ]); + + // Adjust spaces for the imported saved objects. + for (const { objects, spacesToAdd = [], spacesToRemove = [] } of OBJECTS_TO_SHARE) { + log.debug( + `Updating spaces for the following objects (add: [${spacesToAdd.join( + ', ' + )}], remove: [${spacesToRemove.join(', ')}]): ${objects + .map(({ type, id }) => `${type}:${id}`) + .join(', ')}` + ); + await supertest + .post('/api/spaces/_update_objects_spaces') + .send({ objects, spacesToAdd, spacesToRemove }) + .expect(200); + } + }, + + afterEach: async () => { + const allSpacesIds = [ + ...(await spacesService.getAll()).map((space) => space.id), + 'non_existent_space', + ]; + log.debug(`Removing data from the following spaces: ${allSpacesIds.join(', ')}`); + await Promise.all( + allSpacesIds.flatMap((spaceId) => [ + kbnServer.savedObjects.cleanStandardList({ space: spaceId }), + kbnServer.savedObjects.clean({ space: spaceId, types: ['sharedtype', 'isolatedtype'] }), + ]) + ); + }, + }; +} diff --git a/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts b/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts index 72997ead356836..c781eff6d32720 100644 --- a/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts @@ -6,13 +6,16 @@ */ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; -import { EsArchiver } from '@kbn/es-archiver'; -import type { Client } from '@elastic/elasticsearch'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import { CopyResponse } from '@kbn/spaces-plugin/server/lib/copy_to_spaces'; +import { + SavedObjectsImportFailure, + SavedObjectsImportAmbiguousConflictError, +} from '@kbn/core/server'; import { getAggregatedSpaceData, getUrlPrefix } from '../lib/space_test_utils'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; +import { getTestDataLoader } from '../lib/test_data_loader'; +import { FtrProviderContext } from '../ftr_provider_context'; type TestResponse = Record<string, any>; @@ -78,11 +81,11 @@ const getDestinationWithConflicts = (originSpaceId?: string) => interface Aggs extends estypes.AggregationsMultiBucketAggregateBase { buckets: SpaceBucket[]; } -export function copyToSpaceTestSuiteFactory( - es: Client, - esArchiver: EsArchiver, - supertest: SuperTest<any> -) { +export function copyToSpaceTestSuiteFactory(context: FtrProviderContext) { + const testDataLoader = getTestDataLoader(context); + const supertestWithoutAuth = context.getService('supertestWithoutAuth'); + const es = context.getService('es'); + const collectSpaceContents = async () => { const response = await getAggregatedSpaceData(es, [ 'visualization', @@ -693,18 +696,22 @@ export function copyToSpaceTestSuiteFactory( if (createNewCopies) { expectNewCopyResponse(response, ambiguousConflictId, title); } else { + // The `updatedAt` values cannot be determined upfront and hence asserted since we update spaces list + // for certain objects in the test setup. + const importAmbiguousConflictError = (errors as SavedObjectsImportFailure[])?.[0] + .error as SavedObjectsImportAmbiguousConflictError; // It doesn't matter if overwrite is enabled or not, the object will not be copied because there are two matches in the destination space const destinations = [ - // response destinations should be sorted by updatedAt in descending order, then ID in ascending order + // response destinations should be sorted by ID in ascending order { id: 'conflict_2_all', title: 'A shared saved-object in all spaces', - updatedAt: '2017-09-21T18:59:16.270Z', + updatedAt: importAmbiguousConflictError?.destinations[0].updatedAt, }, { id: 'conflict_2_space_2', title: 'A shared saved-object in one space', - updatedAt: '2017-09-21T18:59:16.270Z', + updatedAt: importAmbiguousConflictError?.destinations[1].updatedAt, }, ]; expect(success).to.eql(false); @@ -737,22 +744,20 @@ export function copyToSpaceTestSuiteFactory( { user = {}, spaceId = DEFAULT_SPACE_ID, tests }: CopyToSpaceTestDefinition ) => { describeFn(description, () => { - before(() => { + before(async () => { // test data only allows for the following spaces as the copy origin expect(['default', 'space_1']).to.contain(spaceId); + + await testDataLoader.before(); + }); + + after(async () => { + await testDataLoader.after(); }); describe('single-namespace types', () => { - beforeEach(() => - esArchiver.load( - 'x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces' - ) - ); - afterEach(() => - esArchiver.unload( - 'x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces' - ) - ); + beforeEach(async () => await testDataLoader.beforeEach()); + afterEach(async () => await testDataLoader.afterEach()); const dashboardObject = { type: 'dashboard', id: `cts_dashboard_${spaceId}` }; @@ -761,7 +766,7 @@ export function copyToSpaceTestSuiteFactory( await assertSpaceCounts(destination, INITIAL_COUNTS[destination]); - return supertest + return supertestWithoutAuth .post(`${getUrlPrefix(spaceId)}/api/spaces/_copy_saved_objects`) .auth(user.username, user.password) .send({ @@ -780,7 +785,7 @@ export function copyToSpaceTestSuiteFactory( await assertSpaceCounts(destination, INITIAL_COUNTS[destination]); - return supertest + return supertestWithoutAuth .post(`${getUrlPrefix(spaceId)}/api/spaces/_copy_saved_objects`) .auth(user.username, user.password) .send({ @@ -799,7 +804,7 @@ export function copyToSpaceTestSuiteFactory( await assertSpaceCounts(destination, INITIAL_COUNTS[destination]); - return supertest + return supertestWithoutAuth .post(`${getUrlPrefix(spaceId)}/api/spaces/_copy_saved_objects`) .auth(user.username, user.password) .send({ @@ -818,7 +823,7 @@ export function copyToSpaceTestSuiteFactory( await assertSpaceCounts(destination, INITIAL_COUNTS[destination]); - return supertest + return supertestWithoutAuth .post(`${getUrlPrefix(spaceId)}/api/spaces/_copy_saved_objects`) .auth(user.username, user.password) .send({ @@ -836,7 +841,7 @@ export function copyToSpaceTestSuiteFactory( const conflictDestination = getDestinationWithConflicts(spaceId); const noConflictDestination = getDestinationWithoutConflicts(); - return supertest + return supertestWithoutAuth .post(`${getUrlPrefix(spaceId)}/api/spaces/_copy_saved_objects`) .auth(user.username, user.password) .send({ @@ -869,7 +874,7 @@ export function copyToSpaceTestSuiteFactory( }); it(`should return ${tests.nonExistentSpace.statusCode} when copying to non-existent space`, async () => { - return supertest + return supertestWithoutAuth .post(`${getUrlPrefix(spaceId)}/api/spaces/_copy_saved_objects`) .auth(user.username, user.password) .send({ @@ -893,21 +898,13 @@ export function copyToSpaceTestSuiteFactory( const spaces = ['space_2']; const includeReferences = false; describe(`multi-namespace types with overwrite=${overwrite} and createNewCopies=${createNewCopies}`, () => { - before(() => - esArchiver.load( - 'x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces' - ) - ); - after(() => - esArchiver.unload( - 'x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces' - ) - ); + before(async () => await testDataLoader.beforeEach()); + after(async () => await testDataLoader.afterEach()); const testCases = tests.multiNamespaceTestCases(overwrite, createNewCopies); testCases.forEach(({ testTitle, objects, statusCode, response }) => { it(`should return ${statusCode} when ${testTitle}`, async () => { - return supertest + return supertestWithoutAuth .post(`${getUrlPrefix(spaceId)}/api/spaces/_copy_saved_objects`) .auth(user.username, user.password) .send({ objects, spaces, includeReferences, createNewCopies, overwrite }) diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts index 81018230f4e07e..2a99ae8afceb61 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/copy_to_space.ts @@ -11,11 +11,7 @@ import { copyToSpaceTestSuiteFactory } from '../../common/suites/copy_to_space'; import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export -export default function copyToSpaceSpacesAndSecuritySuite({ getService }: FtrProviderContext) { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const esArchiver = getService('esArchiver'); - const es = getService('es'); - +export default function copyToSpaceSpacesAndSecuritySuite(context: FtrProviderContext) { const { copyToSpaceTest, expectNoConflictsWithoutReferencesResult, @@ -27,10 +23,9 @@ export default function copyToSpaceSpacesAndSecuritySuite({ getService }: FtrPro createExpectUnauthorizedAtSpaceWithoutReferencesResult, expectRouteForbiddenResponse, createMultiNamespaceTestCases, - } = copyToSpaceTestSuiteFactory(es, esArchiver, supertestWithoutAuth); + } = copyToSpaceTestSuiteFactory(context); - // Failing: See https://github.com/elastic/kibana/issues/86544 - describe.skip('copy to spaces', () => { + describe('copy to spaces', () => { [ { spaceId: SPACES.DEFAULT.spaceId, diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts index f5422c1f500850..4139e94610f08c 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/copy_to_space.ts @@ -5,15 +5,11 @@ * 2.0. */ -import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; import { copyToSpaceTestSuiteFactory } from '../../common/suites/copy_to_space'; // eslint-disable-next-line import/no-default-export -export default function copyToSpacesOnlySuite({ getService }: FtrProviderContext) { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const esArchiver = getService('esArchiver'); - const es = getService('es'); - +export default function copyToSpacesOnlySuite(context: FtrProviderContext) { const { copyToSpaceTest, expectNoConflictsWithoutReferencesResult, @@ -23,7 +19,7 @@ export default function copyToSpacesOnlySuite({ getService }: FtrProviderContext createExpectWithConflictsWithoutOverwritingResult, createMultiNamespaceTestCases, originSpaces, - } = copyToSpaceTestSuiteFactory(es, esArchiver, supertestWithoutAuth); + } = copyToSpaceTestSuiteFactory(context); describe('copy to spaces', () => { originSpaces.forEach((spaceId) => { From 340c6fbc527d23198adb8c6459e36cb34df84812 Mon Sep 17 00:00:00 2001 From: Joe Reuter <johannes.reuter@elastic.co> Date: Tue, 13 Sep 2022 12:22:39 +0200 Subject: [PATCH 100/144] Cache all nested formatters (#140480) * cache all nested formatters * fix tests --- .../aggs/utils/get_aggs_formats.test.ts | 6 +-- .../search/aggs/utils/get_aggs_formats.ts | 52 +++++++++---------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts index ea68be542f42f5..eb0d6df57b278d 100644 --- a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts +++ b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.test.ts @@ -42,7 +42,7 @@ describe('getAggsFormats', () => { ); expect(format.convert({ to: '2020-06-01' })).toBe('Before 2020-06-01'); expect(format.convert({ from: '2020-06-01' })).toBe('After 2020-06-01'); - expect(getFormat).toHaveBeenCalledTimes(3); + expect(getFormat).toHaveBeenCalledTimes(1); }); test('date_range does not crash on empty value', () => { @@ -62,7 +62,7 @@ describe('getAggsFormats', () => { expect(format.convert({ type: 'range', to: '10.0.0.10' })).toBe('-Infinity to 10.0.0.10'); expect(format.convert({ type: 'range', from: '10.0.0.10' })).toBe('10.0.0.10 to Infinity'); format.convert({ type: 'mask', mask: '10.0.0.1/24' }); - expect(getFormat).toHaveBeenCalledTimes(4); + expect(getFormat).toHaveBeenCalledTimes(1); }); test('ip_range does not crash on empty value', () => { @@ -135,7 +135,7 @@ describe('getAggsFormats', () => { expect(format.convert('machine.os.keyword')).toBe('machine.os.keyword'); expect(format.convert('__other__')).toBe(mapping.params.otherBucketLabel); expect(format.convert('__missing__')).toBe(mapping.params.missingBucketLabel); - expect(getFormat).toHaveBeenCalledTimes(3); + expect(getFormat).toHaveBeenCalledTimes(1); }); test('uses a default separator for multi terms', () => { diff --git a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts index 5e36fbb791e28f..f9b8dd508d4a90 100644 --- a/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts +++ b/src/plugins/data/common/search/aggs/utils/get_aggs_formats.ts @@ -16,6 +16,7 @@ import { IFieldFormat, SerializedFieldFormat, } from '@kbn/field-formats-plugin/common'; +import { SerializableRecord } from '@kbn/utility-types'; import { DateRange } from '../../expressions'; import { convertDateRangeToString } from '../buckets/lib/date_range'; import { convertIPRangeToString, IpRangeKey } from '../buckets/lib/ip_range'; @@ -35,8 +36,21 @@ type GetFieldFormat = (mapping: SerializedFieldFormat) => IFieldFormat; * @internal */ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInstanceType[] { + class FieldFormatWithCache extends FieldFormat { + protected formatCache: Map<SerializedFieldFormat, FieldFormat> = new Map(); + + protected getCachedFormat(fieldParams: SerializedFieldFormat<{}, SerializableRecord>) { + const isCached = this.formatCache.has(fieldParams); + const cachedFormat = this.formatCache.get(fieldParams) || getFieldFormat(fieldParams); + if (!isCached) { + this.formatCache.set(fieldParams, cachedFormat); + } + return cachedFormat; + } + } + return [ - class AggsRangeFieldFormat extends FieldFormat { + class AggsRangeFieldFormat extends FieldFormatWithCache { static id = 'range'; static hidden = true; @@ -51,10 +65,7 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta return range.label; } const nestedFormatter = params as SerializedFieldFormat; - const format = getFieldFormat({ - id: nestedFormatter.id, - params: nestedFormatter.params, - }); + const format = this.getCachedFormat(nestedFormatter); const gte = '\u2265'; const lt = '\u003c'; @@ -88,7 +99,7 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta }); }; }, - class AggsDateRangeFieldFormat extends FieldFormat { + class AggsDateRangeFieldFormat extends FieldFormatWithCache { static id = 'date_range'; static hidden = true; @@ -98,14 +109,11 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta } const nestedFormatter = this._params as SerializedFieldFormat; - const format = getFieldFormat({ - id: nestedFormatter.id, - params: nestedFormatter.params, - }); + const format = this.getCachedFormat(nestedFormatter); return convertDateRangeToString(range, format.convert.bind(format)); }; }, - class AggsIpRangeFieldFormat extends FieldFormat { + class AggsIpRangeFieldFormat extends FieldFormatWithCache { static id = 'ip_range'; static hidden = true; @@ -115,20 +123,19 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta } const nestedFormatter = this._params as SerializedFieldFormat; - const format = getFieldFormat({ - id: nestedFormatter.id, - params: nestedFormatter.params, - }); + const format = this.getCachedFormat(nestedFormatter); return convertIPRangeToString(range, format.convert.bind(format)); }; }, - class AggsTermsFieldFormat extends FieldFormat { + class AggsTermsFieldFormat extends FieldFormatWithCache { static id = 'terms'; static hidden = true; convert = (val: string, type: FieldFormatsContentType) => { const params = this._params; - const format = getFieldFormat({ id: `${params.id}`, params }); + const format = this.getCachedFormat( + params as SerializedFieldFormat<{}, SerializableRecord> + ); if (val === '__other__') { return `${params.otherBucketLabel}`; @@ -141,21 +148,14 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta }; getConverterFor = (type: FieldFormatsContentType) => (val: string) => this.convert(val, type); }, - class AggsMultiTermsFieldFormat extends FieldFormat { + class AggsMultiTermsFieldFormat extends FieldFormatWithCache { static id = 'multi_terms'; static hidden = true; - private formatCache: Map<SerializedFieldFormat, FieldFormat> = new Map(); - convert = (val: unknown, type: FieldFormatsContentType) => { const params = this._params; const formats = (params.paramsPerField as SerializedFieldFormat[]).map((fieldParams) => { - const isCached = this.formatCache.has(fieldParams); - const cachedFormat = this.formatCache.get(fieldParams) || getFieldFormat(fieldParams); - if (!isCached) { - this.formatCache.set(fieldParams, cachedFormat); - } - return cachedFormat; + return this.getCachedFormat(fieldParams); }); if (String(val) === '__other__') { From 167526da0de3abc61c0347d42a82c6bfbbe760fd Mon Sep 17 00:00:00 2001 From: Luke Gmys <lgmys@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:17:58 +0200 Subject: [PATCH 101/144] [TIP] Add Indicator Overview tab (#140073) * [TIP] Add Indicator Overview tab * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../common/types/indicator.ts | 2 + .../cypress/integration/indicators.spec.ts | 10 +- .../cypress/tasks/login.ts | 12 +- .../cypress/tasks/navigation.ts | 20 --- .../cypress/tasks/select_range.ts | 4 +- .../common/mocks/mock_field_type_map.ts | 4 +- .../public/common/mocks/story_providers.tsx | 49 +++++-- .../public/common/mocks/test_providers.tsx | 25 ++-- .../components/layout/layout.stories.tsx | 15 ++- .../containers/field_types_provider.tsx | 33 +++++ .../public/hooks/use_field_types.ts | 13 ++ .../modules/empty_page/empty_page.stories.tsx | 12 +- .../indicator_field.stories.tsx | 53 -------- .../indicator_field_label/index.tsx | 8 ++ .../indicator_field_label.tsx | 71 +++++++++++ .../indicator_field.test.tsx.snap | 0 .../indicator_field_value/index.tsx | 8 ++ .../indicator_field.stories.tsx | 40 ++++++ .../indicator_field.test.tsx | 26 +--- .../indicator_field_value.tsx} | 12 +- .../indicator_value_actions/index.tsx | 8 ++ .../indicator_value_actions.tsx | 41 ++++++ .../indicator_empty_prompt/index.tsx | 8 ++ .../indicator_empty_prompt.stories.tsx | 24 ++++ .../indicator_empty_prompt.tsx | 37 ++++++ .../indicator_fields_table/index.tsx | 8 ++ .../indicator_fields_table.stories.tsx | 34 +++++ .../indicator_fields_table.tsx | 63 +++++++++ .../indicators_flyout.stories.tsx | 4 - .../indicators_flyout.test.tsx | 85 ++++++------- .../indicators_flyout/indicators_flyout.tsx | 45 ++++--- .../tabs}/indicators_flyout_json/index.tsx | 0 .../indicators_flyout_json.stories.tsx | 2 +- .../indicators_flyout_json.test.tsx | 11 +- .../indicators_flyout_json.tsx | 29 +---- .../components/block}/index.tsx | 2 +- .../block/indicator_block.stories.tsx | 31 +++++ .../components/block/indicator_block.tsx | 69 ++++++++++ .../highlighted_values_table.tsx | 54 ++++++++ .../highlighted_values_table/index.tsx | 8 ++ .../tabs/indicators_flyout_overview/index.tsx | 8 ++ .../indicators_flyout_overview.stories.tsx | 36 ++++++ .../indicators_flyout_overview.test.tsx | 48 +++++++ .../indicators_flyout_overview.tsx | 111 ++++++++++++++++ .../tabs}/indicators_flyout_table/index.tsx | 0 .../indicators_flyout_table.stories.tsx | 18 +-- .../indicators_flyout_table.test.tsx | 19 +-- .../indicators_flyout_table.tsx | 47 +++++++ .../indicators_flyout_table.tsx | 120 ------------------ .../indicators_table/cell_actions.tsx | 4 +- .../indicators_table/cell_renderer.tsx | 6 +- .../components/indicators_table/context.ts | 1 - .../hooks/use_column_settings.ts | 52 ++------ .../indicators_table.stories.tsx | 46 +++---- .../indicators_table/indicators_table.tsx | 22 +--- .../hooks/use_aggregated_indicators.ts | 10 +- .../modules/indicators/indicators_page.tsx | 57 +++++---- .../filter_in_out/filter_in_out.test.tsx | 2 +- .../filter_in_out/filter_in_out.tsx | 4 +- .../add_to_timeline/add_to_timeline.tsx | 6 +- .../scripts/generate_indicators.js | 4 +- .../translations/translations/fr-FR.json | 17 +-- .../translations/translations/ja-JP.json | 17 +-- .../translations/translations/zh-CN.json | 17 +-- 64 files changed, 1102 insertions(+), 550 deletions(-) delete mode 100644 x-pack/plugins/threat_intelligence/cypress/tasks/navigation.ts create mode 100644 x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/hooks/use_field_types.ts delete mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.stories.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/index.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/indicator_field_label.tsx rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{indicator_field => indicator_field_value}/__snapshots__/indicator_field.test.tsx.snap (100%) create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/index.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.stories.tsx rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{indicator_field => indicator_field_value}/indicator_field.test.tsx (63%) rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{indicator_field/indicator_field.tsx => indicator_field_value/indicator_field_value.tsx} (80%) create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/index.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/indicator_value_actions.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/index.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.stories.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/index.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.stories.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.tsx rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{ => indicators_flyout/tabs}/indicators_flyout_json/index.tsx (100%) rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{ => indicators_flyout/tabs}/indicators_flyout_json/indicators_flyout_json.stories.tsx (96%) rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{ => indicators_flyout/tabs}/indicators_flyout_json/indicators_flyout_json.test.tsx (82%) rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{ => indicators_flyout/tabs}/indicators_flyout_json/indicators_flyout_json.tsx (52%) rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{indicator_field => indicators_flyout/tabs/indicators_flyout_overview/components/block}/index.tsx (87%) create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.stories.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/highlighted_values_table.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/index.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/index.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.stories.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.test.tsx create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.tsx rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{ => indicators_flyout/tabs}/indicators_flyout_table/index.tsx (100%) rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{ => indicators_flyout/tabs}/indicators_flyout_table/indicators_flyout_table.stories.tsx (62%) rename x-pack/plugins/threat_intelligence/public/modules/indicators/components/{ => indicators_flyout/tabs}/indicators_flyout_table/indicators_flyout_table.test.tsx (72%) create mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.tsx delete mode 100644 x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.tsx diff --git a/x-pack/plugins/threat_intelligence/common/types/indicator.ts b/x-pack/plugins/threat_intelligence/common/types/indicator.ts index 2edcbb5a829ea6..69e76e18545c1e 100644 --- a/x-pack/plugins/threat_intelligence/common/types/indicator.ts +++ b/x-pack/plugins/threat_intelligence/common/types/indicator.ts @@ -10,6 +10,7 @@ */ export enum RawIndicatorFieldId { Type = 'threat.indicator.type', + Confidence = 'threat.indicator.confidence', FirstSeen = 'threat.indicator.first_seen', LastSeen = 'threat.indicator.last_seen', MarkingTLP = 'threat.indicator.marking.tlp', @@ -44,6 +45,7 @@ export enum RawIndicatorFieldId { TimeStamp = '@timestamp', Id = '_id', Name = 'threat.indicator.name', + Description = 'threat.indicator.description', NameOrigin = 'threat.indicator.name_origin', } diff --git a/x-pack/plugins/threat_intelligence/cypress/integration/indicators.spec.ts b/x-pack/plugins/threat_intelligence/cypress/integration/indicators.spec.ts index d331f2937e41d6..ccd91253012b39 100644 --- a/x-pack/plugins/threat_intelligence/cypress/integration/indicators.spec.ts +++ b/x-pack/plugins/threat_intelligence/cypress/integration/indicators.spec.ts @@ -78,12 +78,16 @@ describe('Indicators', () => { cy.get(TOGGLE_FLYOUT_BUTTON).first().click({ force: true }); - cy.get(FLYOUT_TITLE).should('contain', 'Indicator:'); + cy.get(FLYOUT_TITLE).should('contain', 'Indicator details'); - cy.get(FLYOUT_TABLE).should('exist').and('contain.text', 'threat.indicator.type'); + cy.get(FLYOUT_TABS).should('exist').children().should('have.length', 3); + + cy.get(FLYOUT_TABS).should('exist'); + cy.get(`${FLYOUT_TABS} button:nth-child(2)`).click(); - cy.get(FLYOUT_TABS).should('exist').children().should('have.length', 2).last().click(); + cy.get(FLYOUT_TABLE).should('exist').and('contain.text', 'threat.indicator.type'); + cy.get(`${FLYOUT_TABS} button:nth-child(3)`).click(); cy.get(FLYOUT_JSON).should('exist').and('contain.text', 'threat.indicator.type'); }); }); diff --git a/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts b/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts index 2df7b88f1607b2..f33034dccb9c5e 100644 --- a/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts +++ b/x-pack/plugins/threat_intelligence/cypress/tasks/login.ts @@ -11,7 +11,12 @@ import type { UrlObject } from 'url'; import * as yaml from 'js-yaml'; import type { ROLES } from './privileges'; -import { hostDetailsUrl, LOGOUT_URL } from './navigation'; + +const LOGIN_API_ENDPOINT = '/internal/security/login'; +const LOGOUT_URL = '/logout'; + +export const hostDetailsUrl = (hostName: string) => + `/app/security/hosts/${hostName}/authentications`; /** * Credentials in the `kibana.dev.yml` config file will be used to authenticate @@ -43,11 +48,6 @@ const ELASTICSEARCH_USERNAME = 'ELASTICSEARCH_USERNAME'; */ const ELASTICSEARCH_PASSWORD = 'ELASTICSEARCH_PASSWORD'; -/** - * The Kibana server endpoint used for authentication - */ -const LOGIN_API_ENDPOINT = '/internal/security/login'; - /** * cy.visit will default to the baseUrl which uses the default kibana test user * This function will override that functionality in cy.visit by building the baseUrl diff --git a/x-pack/plugins/threat_intelligence/cypress/tasks/navigation.ts b/x-pack/plugins/threat_intelligence/cypress/tasks/navigation.ts deleted file mode 100644 index 741a2cf761e8c4..00000000000000 --- a/x-pack/plugins/threat_intelligence/cypress/tasks/navigation.ts +++ /dev/null @@ -1,20 +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. - */ - -export const INTEGRATIONS = 'app/integrations#/'; -export const FLEET = 'app/fleet/'; -export const LOGIN_API_ENDPOINT = '/internal/security/login'; -export const LOGOUT_API_ENDPOINT = '/api/security/logout'; -export const LOGIN_URL = '/login'; -export const LOGOUT_URL = '/logout'; - -export const hostDetailsUrl = (hostName: string) => - `/app/security/hosts/${hostName}/authentications`; - -export const navigateTo = (page: string) => { - cy.visit(page); -}; diff --git a/x-pack/plugins/threat_intelligence/cypress/tasks/select_range.ts b/x-pack/plugins/threat_intelligence/cypress/tasks/select_range.ts index 8bf94c7f920ee2..aa654a7c300d32 100644 --- a/x-pack/plugins/threat_intelligence/cypress/tasks/select_range.ts +++ b/x-pack/plugins/threat_intelligence/cypress/tasks/select_range.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { FIELD_BROWSER, TIME_RANGE_PICKER } from '../screens/indicators'; +import { TIME_RANGE_PICKER } from '../screens/indicators'; export const selectRange = () => { - cy.get(FIELD_BROWSER); + cy.get(`[data-test-subj="indicatorsTableEmptyState"]`); cy.get(TIME_RANGE_PICKER).first().click({ force: true }); cy.get('[aria-label="Time unit"]').select('y'); diff --git a/x-pack/plugins/threat_intelligence/public/common/mocks/mock_field_type_map.ts b/x-pack/plugins/threat_intelligence/public/common/mocks/mock_field_type_map.ts index 39a03139f30a4e..90c8da120501e2 100644 --- a/x-pack/plugins/threat_intelligence/public/common/mocks/mock_field_type_map.ts +++ b/x-pack/plugins/threat_intelligence/public/common/mocks/mock_field_type_map.ts @@ -5,10 +5,12 @@ * 2.0. */ +import { FieldTypesContextValue } from '../../containers/field_types_provider'; + /** * Mock to map an indicator field to its type. */ -export const generateFieldTypeMap = (): { [id: string]: string } => ({ +export const generateFieldTypeMap = (): FieldTypesContextValue => ({ '@timestamp': 'date', 'threat.indicator.ip': 'ip', 'threat.indicator.first_seen': 'date', diff --git a/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx b/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx index 6da13f89d08873..a9d808d56be938 100644 --- a/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx +++ b/x-pack/plugins/threat_intelligence/public/common/mocks/story_providers.tsx @@ -5,13 +5,19 @@ * 2.0. */ -import React, { ReactNode, VFC } from 'react'; +import React, { FC, ReactNode, VFC } from 'react'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { IUiSettingsClient } from '@kbn/core/public'; +import { CoreStart, IUiSettingsClient } from '@kbn/core/public'; import { TimelinesUIStart } from '@kbn/timelines-plugin/public'; +import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { SecuritySolutionContext } from '../../containers/security_solution_context'; import { getSecuritySolutionContextMock } from './mock_security_context'; +import { FieldTypesContext } from '../../containers/field_types_provider'; +import { generateFieldTypeMap } from './mock_field_type_map'; +import { mockUiSettingsService } from './mock_kibana_ui_settings_service'; +import { mockKibanaTimelinesService } from './mock_kibana_timelines_service'; +import { mockTriggersActionsUiService } from './mock_kibana_triggers_actions_ui_service'; export interface KibanaContextMock { /** @@ -30,29 +36,54 @@ export interface KibanaContextMock { export interface StoryProvidersComponentProps { /** - * Used to generate a new KibanaReactContext (using {@link createKibanaReactContext}) + * Extend / override mock services specified in {@link defaultServices} to create KibanaReactContext (using {@link createKibanaReactContext}). This is optional. */ - kibana: KibanaContextMock; + kibana?: KibanaContextMock; /** * Component(s) to be displayed inside */ children: ReactNode; } +const securityLayout = { + getPluginWrapper: + (): FC => + ({ children }) => + <div>{children}</div>, +}; + +const defaultServices = { + uiSettings: mockUiSettingsService(), + timelines: mockKibanaTimelinesService, + triggersActionsUi: mockTriggersActionsUiService, + storage: { + set: () => {}, + get: () => {}, + }, +} as unknown as CoreStart; + /** * Helper functional component used in Storybook stories. * Wraps the story with our {@link SecuritySolutionContext} and KibanaReactContext. */ export const StoryProvidersComponent: VFC<StoryProvidersComponentProps> = ({ children, - kibana, + kibana = {}, }) => { - const KibanaReactContext = createKibanaReactContext(kibana); + const KibanaReactContext = createKibanaReactContext({ + ...defaultServices, + ...kibana, + securityLayout, + }); const securitySolutionContextMock = getSecuritySolutionContextMock(); return ( - <SecuritySolutionContext.Provider value={securitySolutionContextMock}> - <KibanaReactContext.Provider>{children}</KibanaReactContext.Provider> - </SecuritySolutionContext.Provider> + <EuiThemeProvider> + <FieldTypesContext.Provider value={generateFieldTypeMap()}> + <SecuritySolutionContext.Provider value={securitySolutionContextMock}> + <KibanaReactContext.Provider>{children}</KibanaReactContext.Provider> + </SecuritySolutionContext.Provider> + </FieldTypesContext.Provider> + </EuiThemeProvider> ); }; diff --git a/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx b/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx index 8648169dfdb4a2..d3a94bbcce96ee 100644 --- a/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx +++ b/x-pack/plugins/threat_intelligence/public/common/mocks/test_providers.tsx @@ -15,6 +15,7 @@ import type { IStorage } from '@kbn/kibana-utils-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; import { createTGridMocks } from '@kbn/timelines-plugin/public/mock'; +import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { KibanaContext } from '../../hooks/use_kibana'; import { SecuritySolutionPluginContext } from '../../types'; import { getSecuritySolutionContextMock } from './mock_security_context'; @@ -22,6 +23,8 @@ import { mockUiSetting } from './mock_kibana_ui_settings_service'; import { SecuritySolutionContext } from '../../containers/security_solution_context'; import { IndicatorsFiltersContext } from '../../modules/indicators/context'; import { mockIndicatorsFiltersContext } from './mock_indicators_filters_context'; +import { FieldTypesContext } from '../../containers/field_types_provider'; +import { generateFieldTypeMap } from './mock_field_type_map'; export const localStorageMock = (): IStorage => { let store: Record<string, unknown> = {}; @@ -122,15 +125,19 @@ export const mockedServices = { }; export const TestProvidersComponent: FC = ({ children }) => ( - <SecuritySolutionContext.Provider value={mockSecurityContext}> - <KibanaContext.Provider value={{ services: mockedServices } as any}> - <I18nProvider> - <IndicatorsFiltersContext.Provider value={mockIndicatorsFiltersContext}> - {children} - </IndicatorsFiltersContext.Provider> - </I18nProvider> - </KibanaContext.Provider> - </SecuritySolutionContext.Provider> + <FieldTypesContext.Provider value={generateFieldTypeMap()}> + <EuiThemeProvider> + <SecuritySolutionContext.Provider value={mockSecurityContext}> + <KibanaContext.Provider value={{ services: mockedServices } as any}> + <I18nProvider> + <IndicatorsFiltersContext.Provider value={mockIndicatorsFiltersContext}> + {children} + </IndicatorsFiltersContext.Provider> + </I18nProvider> + </KibanaContext.Provider> + </SecuritySolutionContext.Provider> + </EuiThemeProvider> + </FieldTypesContext.Provider> ); export type MockedSearch = jest.Mocked<typeof mockedServices.data.search>; diff --git a/x-pack/plugins/threat_intelligence/public/components/layout/layout.stories.tsx b/x-pack/plugins/threat_intelligence/public/components/layout/layout.stories.tsx index e6b73615c61b23..5776af28466883 100644 --- a/x-pack/plugins/threat_intelligence/public/components/layout/layout.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/components/layout/layout.stories.tsx @@ -9,17 +9,22 @@ import React from 'react'; import { Story } from '@storybook/react'; import { EuiText } from '@elastic/eui'; import { DefaultPageLayout } from './layout'; +import { StoryProvidersComponent } from '../../common/mocks/story_providers'; export default { - component: DefaultPageLayout, title: 'DefaultPageLayout', + component: DefaultPageLayout, }; export const Default: Story<void> = () => { const title = 'Title with border below'; const children = <EuiText>Content with border above</EuiText>; - return <DefaultPageLayout pageTitle={title} children={children} />; + return ( + <StoryProvidersComponent> + <DefaultPageLayout pageTitle={title} children={children} /> + </StoryProvidersComponent> + ); }; export const NoBorder: Story<void> = () => { @@ -27,5 +32,9 @@ export const NoBorder: Story<void> = () => { const border = false; const children = <EuiText>Content without border</EuiText>; - return <DefaultPageLayout pageTitle={title} border={border} children={children} />; + return ( + <StoryProvidersComponent> + <DefaultPageLayout pageTitle={title} border={border} children={children} /> + </StoryProvidersComponent> + ); }; diff --git a/x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx b/x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx new file mode 100644 index 00000000000000..050ecb4a3fe102 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/containers/field_types_provider.tsx @@ -0,0 +1,33 @@ +/* + * 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, { createContext, useMemo } from 'react'; +import { FC } from 'react'; +import { useSourcererDataView } from '../modules/indicators/hooks/use_sourcerer_data_view'; + +export type FieldTypesContextValue = Record<string, string | undefined>; + +export const FieldTypesContext = createContext<FieldTypesContextValue | undefined>({}); + +/** + * Exposes mapped field types for threat intel shared use + */ +export const FieldTypesProvider: FC = ({ children }) => { + const { indexPattern } = useSourcererDataView(); + + // field name to field type map to allow the cell_renderer to format dates + const fieldTypes: FieldTypesContextValue = useMemo( + () => + indexPattern.fields.reduce((acc, field) => { + acc[field.name] = field.type; + return acc; + }, {} as FieldTypesContextValue), + [indexPattern.fields] + ); + + return <FieldTypesContext.Provider value={fieldTypes}>{children}</FieldTypesContext.Provider>; +}; diff --git a/x-pack/plugins/threat_intelligence/public/hooks/use_field_types.ts b/x-pack/plugins/threat_intelligence/public/hooks/use_field_types.ts new file mode 100644 index 00000000000000..66ae2456e2dcf2 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/hooks/use_field_types.ts @@ -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. + */ + +import { useContext } from 'react'; +import { FieldTypesContext } from '../containers/field_types_provider'; + +export const useFieldTypes = () => { + return useContext(FieldTypesContext) || {}; +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/empty_page/empty_page.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/empty_page/empty_page.stories.tsx index d284fe24052bcc..bc298ef95eecf7 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/empty_page/empty_page.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/empty_page/empty_page.stories.tsx @@ -6,9 +6,8 @@ */ import React from 'react'; -import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; -import { CoreStart } from '@kbn/core/public'; import { EmptyPage } from '.'; +import { StoryProvidersComponent } from '../../common/mocks/story_providers'; export default { component: BasicEmptyPage, @@ -16,7 +15,7 @@ export default { }; export function BasicEmptyPage() { - const KibanaReactContext = createKibanaReactContext({ + const kibana = { http: { basePath: { get: () => '', @@ -29,10 +28,11 @@ export function BasicEmptyPage() { }, }, }, - } as unknown as Partial<CoreStart>); + }; + return ( - <KibanaReactContext.Provider> + <StoryProvidersComponent kibana={kibana as any}> <EmptyPage /> - </KibanaReactContext.Provider> + </StoryProvidersComponent> ); } diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.stories.tsx deleted file mode 100644 index 467ff2ea16cf36..00000000000000 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.stories.tsx +++ /dev/null @@ -1,53 +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 React from 'react'; -import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; -import { generateFieldTypeMap } from '../../../../common/mocks/mock_field_type_map'; -import { mockUiSettingsService } from '../../../../common/mocks/mock_kibana_ui_settings_service'; -import { generateMockIndicator } from '../../../../../common/types/indicator'; -import { IndicatorField } from './indicator_field'; - -export default { - component: IndicatorField, - title: 'IndicatorField', -}; - -const mockIndicator = generateMockIndicator(); - -const mockFieldTypesMap = generateFieldTypeMap(); - -export function Default() { - const mockField = 'threat.indicator.ip'; - - return ( - <IndicatorField indicator={mockIndicator} field={mockField} fieldTypesMap={mockFieldTypesMap} /> - ); -} - -export function IncorrectField() { - const mockField = 'abc'; - - return ( - <IndicatorField indicator={mockIndicator} field={mockField} fieldTypesMap={mockFieldTypesMap} /> - ); -} - -export function HandlesDates() { - const KibanaReactContext = createKibanaReactContext({ uiSettings: mockUiSettingsService() }); - const mockField = 'threat.indicator.first_seen'; - - return ( - <KibanaReactContext.Provider> - <IndicatorField - indicator={mockIndicator} - field={mockField} - fieldTypesMap={mockFieldTypesMap} - /> - </KibanaReactContext.Provider> - ); -} diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/index.tsx new file mode 100644 index 00000000000000..a2f2520c9541bd --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/index.tsx @@ -0,0 +1,8 @@ +/* + * 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 './indicator_field_label'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/indicator_field_label.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/indicator_field_label.tsx new file mode 100644 index 00000000000000..64e85bc8c5d7e0 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_label/indicator_field_label.tsx @@ -0,0 +1,71 @@ +/* + * 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, { VFC } from 'react'; +import { i18n } from '@kbn/i18n'; +import { RawIndicatorFieldId } from '../../../../../common/types/indicator'; + +interface IndicatorFieldLabelProps { + field: string; +} + +/** + * Renders field label using i18n, or the field key if the translation is not available + */ +export const IndicatorFieldLabel: VFC<IndicatorFieldLabelProps> = ({ field }) => ( + <>{translateFieldLabel(field)}</> +); + +/** This translates the field name using kbn-i18n */ +export const translateFieldLabel = (field: string) => { + // This switch is necessary as i18n id cannot be dynamic, see: + // https://github.com/elastic/kibana/blob/main/src/dev/i18n/README.md + switch (field) { + case RawIndicatorFieldId.TimeStamp: { + return i18n.translate('xpack.threatIntelligence.field.@timestamp', { + defaultMessage: '@timestamp', + }); + } + case RawIndicatorFieldId.Name: { + return i18n.translate('xpack.threatIntelligence.field.threat.indicator.name', { + defaultMessage: 'Indicator', + }); + } + case RawIndicatorFieldId.Type: { + return i18n.translate('xpack.threatIntelligence.field.threat.indicator.type', { + defaultMessage: 'Indicator type', + }); + } + case RawIndicatorFieldId.Feed: { + return i18n.translate('xpack.threatIntelligence.field.threat.feed.name', { + defaultMessage: 'Feed', + }); + } + case RawIndicatorFieldId.FirstSeen: { + return i18n.translate('xpack.threatIntelligence.field.threat.indicator.first_seen', { + defaultMessage: 'First seen', + }); + } + case RawIndicatorFieldId.LastSeen: { + return i18n.translate('xpack.threatIntelligence.field.threat.indicator.last_seen', { + defaultMessage: 'Last seen', + }); + } + case RawIndicatorFieldId.Confidence: { + return i18n.translate('xpack.threatIntelligence.field.threat.indicator.confidence', { + defaultMessage: 'Confidence', + }); + } + case RawIndicatorFieldId.MarkingTLP: { + return i18n.translate('xpack.threatIntelligence.field.threat.indicator.marking.tlp', { + defaultMessage: 'TLP Marking', + }); + } + default: + return field; + } +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/__snapshots__/indicator_field.test.tsx.snap b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/__snapshots__/indicator_field.test.tsx.snap similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/__snapshots__/indicator_field.test.tsx.snap rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/__snapshots__/indicator_field.test.tsx.snap diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/index.tsx new file mode 100644 index 00000000000000..724caf3c752430 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/index.tsx @@ -0,0 +1,8 @@ +/* + * 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 './indicator_field_value'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.stories.tsx new file mode 100644 index 00000000000000..9548691e49ec51 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.stories.tsx @@ -0,0 +1,40 @@ +/* + * 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 { StoryProvidersComponent } from '../../../../common/mocks/story_providers'; +import { generateMockIndicator } from '../../../../../common/types/indicator'; +import { IndicatorFieldValue } from './indicator_field_value'; + +export default { + component: IndicatorFieldValue, + title: 'IndicatorFieldValue', +}; + +const mockIndicator = generateMockIndicator(); + +export function Default() { + const mockField = 'threat.indicator.ip'; + + return <IndicatorFieldValue indicator={mockIndicator} field={mockField} />; +} + +export function IncorrectField() { + const mockField = 'abc'; + + return <IndicatorFieldValue indicator={mockIndicator} field={mockField} />; +} + +export function HandlesDates() { + const mockField = 'threat.indicator.first_seen'; + + return ( + <StoryProvidersComponent> + <IndicatorFieldValue indicator={mockIndicator} field={mockField} /> + </StoryProvidersComponent> + ); +} diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.test.tsx similarity index 63% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.test.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.test.tsx index 0cd77b95b7b1a2..c695a2c4ebe847 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field.test.tsx @@ -7,39 +7,25 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { IndicatorField } from './indicator_field'; +import { IndicatorFieldValue } from './indicator_field_value'; import { generateMockIndicator } from '../../../../../common/types/indicator'; import { EMPTY_VALUE } from '../../../../../common/constants'; import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; -import { generateFieldTypeMap } from '../../../../common/mocks/mock_field_type_map'; const mockIndicator = generateMockIndicator(); -const mockFieldTypesMap = generateFieldTypeMap(); describe('<IndicatorField />', () => { beforeEach(() => {}); it('should return non formatted value', () => { const mockField = 'threat.indicator.ip'; - const component = render( - <IndicatorField - indicator={mockIndicator} - field={mockField} - fieldTypesMap={mockFieldTypesMap} - /> - ); + const component = render(<IndicatorFieldValue indicator={mockIndicator} field={mockField} />); expect(component).toMatchSnapshot(); }); it(`should return ${EMPTY_VALUE}`, () => { const mockField = 'abc'; - const component = render( - <IndicatorField - indicator={mockIndicator} - field={mockField} - fieldTypesMap={mockFieldTypesMap} - /> - ); + const component = render(<IndicatorFieldValue indicator={mockIndicator} field={mockField} />); expect(component).toMatchSnapshot(); }); @@ -47,11 +33,7 @@ describe('<IndicatorField />', () => { const mockField = 'threat.indicator.first_seen'; const component = render( <TestProvidersComponent> - <IndicatorField - indicator={mockIndicator} - field={mockField} - fieldTypesMap={mockFieldTypesMap} - /> + <IndicatorFieldValue indicator={mockIndicator} field={mockField} /> </TestProvidersComponent> ); expect(component).toMatchSnapshot(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field_value.tsx similarity index 80% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field_value.tsx index 6ea779c28be295..c0b46cd1b44b0f 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/indicator_field.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field_value/indicator_field_value.tsx @@ -6,12 +6,13 @@ */ import React, { VFC } from 'react'; +import { useFieldTypes } from '../../../../hooks/use_field_types'; import { EMPTY_VALUE } from '../../../../../common/constants'; import { Indicator, RawIndicatorFieldId } from '../../../../../common/types/indicator'; import { DateFormatter } from '../../../../components/date_formatter'; import { unwrapValue } from '../../lib/unwrap_value'; -export interface IndicatorFieldProps { +export interface IndicatorFieldValueProps { /** * Indicator to display the field value from (see {@link Indicator}). */ @@ -20,19 +21,16 @@ export interface IndicatorFieldProps { * The field to get the indicator's value for. */ field: string; - /** - * An object to know what type the field is ('file', 'date', ...). - */ - fieldTypesMap: { [id: string]: string }; } /** * Takes an indicator object, a field and a field => type object to returns the correct value to display. * @returns If the type is a 'date', returns the {@link DateFormatter} component, else returns the value or {@link EMPTY_VALUE}. */ -export const IndicatorField: VFC<IndicatorFieldProps> = ({ indicator, field, fieldTypesMap }) => { +export const IndicatorFieldValue: VFC<IndicatorFieldValueProps> = ({ indicator, field }) => { + const fieldType = useFieldTypes()[field]; + const value = unwrapValue(indicator, field as RawIndicatorFieldId); - const fieldType = fieldTypesMap[field]; return fieldType === 'date' ? ( <DateFormatter date={value as string} /> ) : value ? ( diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/index.tsx new file mode 100644 index 00000000000000..1e268b953ef094 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/index.tsx @@ -0,0 +1,8 @@ +/* + * 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 './indicator_value_actions'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/indicator_value_actions.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/indicator_value_actions.tsx new file mode 100644 index 00000000000000..94ec2cf2726cd7 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_value_actions/indicator_value_actions.tsx @@ -0,0 +1,41 @@ +/* + * 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 type { EuiButtonEmpty, EuiButtonIcon } from '@elastic/eui'; +import React, { VFC } from 'react'; +import { EMPTY_VALUE } from '../../../../../common/constants'; +import { Indicator } from '../../../../../common/types/indicator'; +import { FilterInOut } from '../../../query_bar/components/filter_in_out'; +import { AddToTimeline } from '../../../timeline/components/add_to_timeline'; +import { getIndicatorFieldAndValue } from '../../lib/field_value'; + +interface IndicatorValueActions { + indicator: Indicator; + Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon; + field: string; + testId?: string; +} + +export const IndicatorValueActions: VFC<IndicatorValueActions> = ({ + indicator, + field, + testId, + Component, +}) => { + const { key, value } = getIndicatorFieldAndValue(indicator, field); + + if (!key || value === EMPTY_VALUE || !key) { + return null; + } + + return ( + <> + <FilterInOut as={Component} data={indicator} field={field} /> + <AddToTimeline as={Component} data={indicator} field={field} testId={testId} /> + </> + ); +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/index.tsx new file mode 100644 index 00000000000000..a2b896781739c3 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/index.tsx @@ -0,0 +1,8 @@ +/* + * 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 './indicator_empty_prompt'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.stories.tsx new file mode 100644 index 00000000000000..56d66781d187d8 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.stories.tsx @@ -0,0 +1,24 @@ +/* + * 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 { Story } from '@storybook/react'; +import { StoryProvidersComponent } from '../../../../../../common/mocks/story_providers'; +import { IndicatorEmptyPrompt } from './indicator_empty_prompt'; + +export default { + component: IndicatorEmptyPrompt, + title: 'IndicatorEmptyPrompt', +}; + +export const Default: Story<void> = () => { + return ( + <StoryProvidersComponent> + <IndicatorEmptyPrompt /> + </StoryProvidersComponent> + ); +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.tsx new file mode 100644 index 00000000000000..0edf3e67f3c03b --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_empty_prompt/indicator_empty_prompt.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 { EuiEmptyPrompt } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { VFC } from 'react'; + +export const EMPTY_PROMPT_TEST_ID = 'indicatorEmptyPrompt'; + +export const IndicatorEmptyPrompt: VFC = () => ( + <EuiEmptyPrompt + iconType="alert" + color="danger" + title={ + <h2> + <FormattedMessage + id="xpack.threatIntelligence.indicator.flyoutTable.errorMessageTitle" + defaultMessage="Unable to display indicator information" + /> + </h2> + } + body={ + <p> + <FormattedMessage + id="xpack.threatIntelligence.indicator.flyoutTable.errorMessageBody" + defaultMessage="There was an error displaying the indicator fields and values." + /> + </p> + } + data-test-subj={EMPTY_PROMPT_TEST_ID} + /> +); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/index.tsx new file mode 100644 index 00000000000000..9252945c8f5520 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/index.tsx @@ -0,0 +1,8 @@ +/* + * 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 './indicator_fields_table'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.stories.tsx new file mode 100644 index 00000000000000..c867eda97389f5 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.stories.tsx @@ -0,0 +1,34 @@ +/* + * 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 { mockIndicatorsFiltersContext } from '../../../../../../common/mocks/mock_indicators_filters_context'; +import { IndicatorFieldsTable } from './indicator_fields_table'; +import { generateMockIndicator } from '../../../../../../../common/types/indicator'; +import { StoryProvidersComponent } from '../../../../../../common/mocks/story_providers'; +import { IndicatorsFiltersContext } from '../../../../context'; + +export default { + component: IndicatorFieldsTable, + title: 'IndicatorFieldsTable', +}; + +export function WithIndicators() { + const indicator = generateMockIndicator(); + + return ( + <StoryProvidersComponent> + <IndicatorsFiltersContext.Provider value={mockIndicatorsFiltersContext}> + <IndicatorFieldsTable + fields={['threat.indicator.type']} + indicator={indicator} + search={false} + /> + </IndicatorsFiltersContext.Provider> + </StoryProvidersComponent> + ); +} diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.tsx new file mode 100644 index 00000000000000..846417c8cd021d --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/components/indicator_fields_table/indicator_fields_table.tsx @@ -0,0 +1,63 @@ +/* + * 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 { EuiBasicTableColumn, EuiInMemoryTable, EuiInMemoryTableProps } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React, { useMemo, VFC } from 'react'; +import { Indicator } from '../../../../../../../common/types/indicator'; +import { IndicatorFieldValue } from '../../../indicator_field_value'; +import { IndicatorValueActions } from '../../../indicator_value_actions'; + +export interface IndicatorFieldsTableProps { + fields: string[]; + indicator: Indicator; + search: EuiInMemoryTableProps<string>['search']; + ['data-test-subj']?: string; +} + +export const IndicatorFieldsTable: VFC<IndicatorFieldsTableProps> = ({ + fields, + indicator, + ...rest +}) => { + const columns = useMemo( + () => + [ + { + name: ( + <FormattedMessage + id="xpack.threatIntelligence.indicator.fieldsTable.fieldColumnLabel" + defaultMessage="Field" + /> + ), + render: (field: string) => field, + }, + { + name: ( + <FormattedMessage + id="xpack.threatIntelligence.indicator.fieldsTable.valueColumnLabel" + defaultMessage="Value" + /> + ), + render: (field: string) => <IndicatorFieldValue indicator={indicator} field={field} />, + }, + { + actions: [ + { + render: (field: string) => ( + <IndicatorValueActions field={field} indicator={indicator} /> + ), + width: '72px', + }, + ], + }, + ] as Array<EuiBasicTableColumn<string>>, + [indicator] + ); + + return <EuiInMemoryTable items={fields} columns={columns} sorting={true} {...rest} />; +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.stories.tsx index 5076b1649635e2..ec87259c90a58a 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.stories.tsx @@ -10,7 +10,6 @@ import { Story } from '@storybook/react'; import { CoreStart } from '@kbn/core/public'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indicators_filters_context'; -import { generateFieldTypeMap } from '../../../../common/mocks/mock_field_type_map'; import { mockUiSettingsService } from '../../../../common/mocks/mock_kibana_ui_settings_service'; import { mockKibanaTimelinesService } from '../../../../common/mocks/mock_kibana_timelines_service'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; @@ -30,14 +29,12 @@ const KibanaReactContext = createKibanaReactContext(coreMock); export const Default: Story<void> = () => { const mockIndicator: Indicator = generateMockIndicator(); - const mockFieldTypesMap = generateFieldTypeMap(); return ( <KibanaReactContext.Provider> <IndicatorsFiltersContext.Provider value={mockIndicatorsFiltersContext}> <IndicatorsFlyout indicator={mockIndicator} - fieldTypesMap={mockFieldTypesMap} closeFlyout={() => window.alert('Closing flyout')} /> </IndicatorsFiltersContext.Provider> @@ -51,7 +48,6 @@ export const EmptyIndicator: Story<void> = () => { <IndicatorsFiltersContext.Provider value={mockIndicatorsFiltersContext}> <IndicatorsFlyout indicator={{ fields: {} } as Indicator} - fieldTypesMap={{}} closeFlyout={() => window.alert('Closing flyout')} /> </IndicatorsFiltersContext.Provider> diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.test.tsx index 4ad5c0e5f038a4..08add53bafcb10 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.test.tsx @@ -6,66 +6,57 @@ */ import React from 'react'; -import { render } from '@testing-library/react'; +import { cleanup, render, screen } from '@testing-library/react'; import { IndicatorsFlyout, SUBTITLE_TEST_ID, TITLE_TEST_ID } from './indicators_flyout'; -import { generateMockIndicator, RawIndicatorFieldId } from '../../../../../common/types/indicator'; -import { EMPTY_VALUE } from '../../../../../common/constants'; -import { dateFormatter } from '../../../../common/utils/dates'; -import { mockUiSetting } from '../../../../common/mocks/mock_kibana_ui_settings_service'; +import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; -import { generateFieldTypeMap } from '../../../../common/mocks/mock_field_type_map'; -import { unwrapValue } from '../../lib/unwrap_value'; const mockIndicator = generateMockIndicator(); -const mockFieldTypesMap = generateFieldTypeMap(); describe('<IndicatorsFlyout />', () => { - it('should render ioc id in title and first_seen in subtitle', () => { - const { getByTestId } = render( + beforeEach(() => { + render( <TestProvidersComponent> - <IndicatorsFlyout - indicator={mockIndicator} - fieldTypesMap={mockFieldTypesMap} - closeFlyout={() => {}} - /> + <IndicatorsFlyout indicator={mockIndicator} closeFlyout={() => {}} /> </TestProvidersComponent> ); - - expect(getByTestId(TITLE_TEST_ID).innerHTML).toContain( - `Indicator: ${unwrapValue(mockIndicator, RawIndicatorFieldId.Name)}` - ); - expect(getByTestId(SUBTITLE_TEST_ID).innerHTML).toContain( - `First seen: ${dateFormatter( - unwrapValue(mockIndicator, RawIndicatorFieldId.FirstSeen) as string, - mockUiSetting('dateFormat:tz') as string, - mockUiSetting('dateFormat') as string - )}` - ); }); - it(`should render ${EMPTY_VALUE} in on invalid indicator first_seen value`, () => { - const { getByTestId } = render( - <TestProvidersComponent> - <IndicatorsFlyout indicator={{ fields: {} }} fieldTypesMap={{}} closeFlyout={() => {}} /> - </TestProvidersComponent> - ); + it('should render all the tab switches', () => { + expect(screen.queryByTestId('tiIndicatorFlyoutTabs')).toBeInTheDocument(); - expect(getByTestId(TITLE_TEST_ID).innerHTML).toContain(`Indicator: ${EMPTY_VALUE}`); - expect(getByTestId(SUBTITLE_TEST_ID).innerHTML).toContain(`First seen: ${EMPTY_VALUE}`); - }); + const switchElement = screen.getByTestId('tiIndicatorFlyoutTabs'); - it(`should render ${EMPTY_VALUE} in title and subtitle on invalid indicator`, () => { - const { getByTestId } = render( - <TestProvidersComponent> - <IndicatorsFlyout - indicator={{ fields: { 'threat.indicator.first_seen': ['abc'] } }} - fieldTypesMap={mockFieldTypesMap} - closeFlyout={() => {}} - /> - </TestProvidersComponent> - ); + expect(switchElement).toHaveTextContent(/Overview/); + expect(switchElement).toHaveTextContent(/Table/); + expect(switchElement).toHaveTextContent(/JSON/); + }); - expect(getByTestId(TITLE_TEST_ID).innerHTML).toContain(`Indicator: ${EMPTY_VALUE}`); - expect(getByTestId(SUBTITLE_TEST_ID).innerHTML).toContain(`First seen: ${EMPTY_VALUE}`); + describe('title and subtitle', () => { + describe('valid indicator', () => { + it('should render correct title and subtitle', async () => { + expect(screen.getByTestId(TITLE_TEST_ID)).toHaveTextContent('Indicator details'); + }); + }); + + describe('invalid indicator', () => { + beforeEach(() => { + cleanup(); + + render( + <TestProvidersComponent> + <IndicatorsFlyout + indicator={{ fields: {} } as unknown as Indicator} + closeFlyout={() => {}} + /> + </TestProvidersComponent> + ); + }); + + it('should render correct labels', () => { + expect(screen.getByTestId(TITLE_TEST_ID)).toHaveTextContent('Indicator details'); + expect(screen.getByTestId(SUBTITLE_TEST_ID)).toHaveTextContent('First seen: -'); + }); + }); }); }); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.tsx index f1dde44d05aabb..4026980ae1c892 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/indicators_flyout.tsx @@ -19,17 +19,18 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { DateFormatter } from '../../../../components/date_formatter/date_formatter'; -import { EMPTY_VALUE } from '../../../../../common/constants'; import { Indicator, RawIndicatorFieldId } from '../../../../../common/types/indicator'; -import { IndicatorsFlyoutJson } from '../indicators_flyout_json/indicators_flyout_json'; -import { IndicatorsFlyoutTable } from '../indicators_flyout_table/indicators_flyout_table'; +import { IndicatorsFlyoutJson } from './tabs/indicators_flyout_json/indicators_flyout_json'; +import { IndicatorsFlyoutTable } from './tabs/indicators_flyout_table/indicators_flyout_table'; import { unwrapValue } from '../../lib/unwrap_value'; +import { IndicatorsFlyoutOverview } from './tabs/indicators_flyout_overview'; export const TITLE_TEST_ID = 'tiIndicatorFlyoutTitle'; export const SUBTITLE_TEST_ID = 'tiIndicatorFlyoutSubtitle'; export const TABS_TEST_ID = 'tiIndicatorFlyoutTabs'; const enum TAB_IDS { + overview, table, json, } @@ -39,10 +40,6 @@ export interface IndicatorsFlyoutProps { * Indicator passed down to the different tabs (table and json views). */ indicator: Indicator; - /** - * Object mapping each field with their type to ease display in the {@link IndicatorsFlyoutTable} component. - */ - fieldTypesMap: { [id: string]: string }; /** * Event to close flyout (used by {@link EuiFlyout}). */ @@ -52,15 +49,26 @@ export interface IndicatorsFlyoutProps { /** * Leverages the {@link EuiFlyout} from the @elastic/eui library to dhow the details of a specific {@link Indicator}. */ -export const IndicatorsFlyout: VFC<IndicatorsFlyoutProps> = ({ - indicator, - fieldTypesMap, - closeFlyout, -}) => { - const [selectedTabId, setSelectedTabId] = useState(TAB_IDS.table); +export const IndicatorsFlyout: VFC<IndicatorsFlyoutProps> = ({ indicator, closeFlyout }) => { + const [selectedTabId, setSelectedTabId] = useState(TAB_IDS.overview); const tabs = useMemo( () => [ + { + id: TAB_IDS.overview, + name: ( + <FormattedMessage + id="xpack.threatIntelligence.indicator.flyout.overviewTabLabel" + defaultMessage="Overview" + /> + ), + content: ( + <IndicatorsFlyoutOverview + indicator={indicator} + onViewAllFieldsInTable={() => setSelectedTabId(TAB_IDS.table)} + /> + ), + }, { id: TAB_IDS.table, name: ( @@ -69,7 +77,7 @@ export const IndicatorsFlyout: VFC<IndicatorsFlyoutProps> = ({ defaultMessage="Table" /> ), - content: <IndicatorsFlyoutTable indicator={indicator} fieldTypesMap={fieldTypesMap} />, + content: <IndicatorsFlyoutTable indicator={indicator} />, }, { id: TAB_IDS.json, @@ -82,7 +90,7 @@ export const IndicatorsFlyout: VFC<IndicatorsFlyoutProps> = ({ content: <IndicatorsFlyoutJson indicator={indicator} />, }, ], - [indicator, fieldTypesMap] + [indicator] ); const onSelectedTabChanged = (id: number) => setSelectedTabId(id); @@ -102,7 +110,7 @@ export const IndicatorsFlyout: VFC<IndicatorsFlyoutProps> = ({ ); const firstSeen: string = unwrapValue(indicator, RawIndicatorFieldId.FirstSeen) as string; - const displayNameValue = unwrapValue(indicator, RawIndicatorFieldId.Name) || EMPTY_VALUE; + const flyoutTitleId = useGeneratedHtmlId({ prefix: 'simpleFlyoutTitle', }); @@ -113,9 +121,8 @@ export const IndicatorsFlyout: VFC<IndicatorsFlyoutProps> = ({ <EuiTitle> <h2 data-test-subj={TITLE_TEST_ID} id={flyoutTitleId}> <FormattedMessage - id="xpack.threatIntelligence.indicator.flyout.panelTitle" - defaultMessage="Indicator: {title}" - values={{ title: displayNameValue }} + id="xpack.threatIntelligence.indicator.flyout.panelTitleWithOverviewTab" + defaultMessage="Indicator details" /> </h2> </EuiTitle> diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/index.tsx similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/index.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/index.tsx diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.stories.tsx similarity index 96% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.stories.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.stories.tsx index 447dcfcdda6eee..1e40c23a26d4de 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.stories.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { Story } from '@storybook/react'; -import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; +import { generateMockIndicator, Indicator } from '../../../../../../../common/types/indicator'; import { IndicatorsFlyoutJson } from './indicators_flyout_json'; export default { diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.test.tsx similarity index 82% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.test.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.test.tsx index 3310a4e1c893c2..a468db60a023e7 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.test.tsx @@ -7,16 +7,13 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; -import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; -import { - CODE_BLOCK_TEST_ID, - EMPTY_PROMPT_TEST_ID, - IndicatorsFlyoutJson, -} from './indicators_flyout_json'; +import { TestProvidersComponent } from '../../../../../../common/mocks/test_providers'; +import { generateMockIndicator, Indicator } from '../../../../../../../common/types/indicator'; +import { CODE_BLOCK_TEST_ID, IndicatorsFlyoutJson } from './indicators_flyout_json'; const mockIndicator: Indicator = generateMockIndicator(); +import { EMPTY_PROMPT_TEST_ID } from '../../components/indicator_empty_prompt'; describe('<IndicatorsFlyoutJson />', () => { it('should render code block component on valid indicator', () => { const { getByTestId } = render( diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.tsx similarity index 52% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.tsx index 6bc42b1980c201..99c4bcfb0d50f7 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_json/indicators_flyout_json.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_json/indicators_flyout_json.tsx @@ -6,11 +6,10 @@ */ import React, { VFC } from 'react'; -import { EuiCodeBlock, EuiEmptyPrompt } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { Indicator } from '../../../../../common/types/indicator'; +import { EuiCodeBlock } from '@elastic/eui'; +import { Indicator } from '../../../../../../../common/types/indicator'; +import { IndicatorEmptyPrompt } from '../../components/indicator_empty_prompt'; -export const EMPTY_PROMPT_TEST_ID = 'tiFlyoutJsonEmptyPrompt'; export const CODE_BLOCK_TEST_ID = 'tiFlyoutJsonCodeBlock'; export interface IndicatorsFlyoutJsonProps { @@ -26,27 +25,7 @@ export interface IndicatorsFlyoutJsonProps { */ export const IndicatorsFlyoutJson: VFC<IndicatorsFlyoutJsonProps> = ({ indicator }) => { return Object.keys(indicator).length === 0 ? ( - <EuiEmptyPrompt - iconType="alert" - color="danger" - title={ - <h2> - <FormattedMessage - id="xpack.threatIntelligence.indicator.flyoutJson.errorMessageTitle" - defaultMessage="Unable to display indicator information" - /> - </h2> - } - body={ - <p> - <FormattedMessage - id="xpack.threatIntelligence.indicator.flyoutJson.errorMessageBody" - defaultMessage="There was an error displaying the indicator fields and values." - /> - </p> - } - data-test-subj={EMPTY_PROMPT_TEST_ID} - /> + <IndicatorEmptyPrompt /> ) : ( <EuiCodeBlock language="json" lineNumbers data-test-subj={CODE_BLOCK_TEST_ID}> {JSON.stringify(indicator, null, 2)} diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/index.tsx similarity index 87% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/index.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/index.tsx index acea79493c0be8..dbad4c02ee5dce 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicator_field/index.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/index.tsx @@ -5,4 +5,4 @@ * 2.0. */ -export * from './indicator_field'; +export * from './indicator_block'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.stories.tsx new file mode 100644 index 00000000000000..32966e72c2eec2 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.stories.tsx @@ -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 React from 'react'; +import { IndicatorsFiltersContext } from '../../../../../../context'; +import { StoryProvidersComponent } from '../../../../../../../../common/mocks/story_providers'; +import { generateMockIndicator } from '../../../../../../../../../common/types/indicator'; +import { IndicatorBlock } from './indicator_block'; + +export default { + component: IndicatorBlock, + title: 'IndicatorBlock', +}; + +const mockIndicator = generateMockIndicator(); + +export function Default() { + const mockField = 'threat.indicator.ip'; + + return ( + <StoryProvidersComponent> + <IndicatorsFiltersContext.Provider value={{} as any}> + <IndicatorBlock indicator={mockIndicator} field={mockField} /> + </IndicatorsFiltersContext.Provider> + </StoryProvidersComponent> + ); +} diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.tsx new file mode 100644 index 00000000000000..a6f5c5a387c170 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/block/indicator_block.tsx @@ -0,0 +1,69 @@ +/* + * 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 { EuiPanel, EuiSpacer, EuiText } from '@elastic/eui'; +import React, { VFC } from 'react'; +import { euiStyled, css } from '@kbn/kibana-react-plugin/common'; +import { Indicator } from '../../../../../../../../../common/types/indicator'; +import { IndicatorFieldValue } from '../../../../../indicator_field_value'; +import { IndicatorFieldLabel } from '../../../../../indicator_field_label'; +import { IndicatorValueActions } from '../../../../../indicator_value_actions'; + +/** + * Show actions wrapper on hover. This is a helper component, limited only to Block + */ +const VisibleOnHover = euiStyled.div` + ${({ theme }) => css` + & { + height: 100%; + } + + & .actionsWrapper { + visibility: hidden; + display: inline-block; + margin-inline-start: ${theme.eui.euiSizeXS}; + } + + &:hover .actionsWrapper { + visibility: visible; + } + `} +`; + +const panelProps = { + color: 'subdued' as const, + hasShadow: false, + borderRadius: 'none' as const, + paddingSize: 's' as const, +}; + +export interface IndicatorBlockProps { + indicator: Indicator; + field: string; +} + +/** + * Renders indicator field value in a rectangle, to highlight it even more + */ +export const IndicatorBlock: VFC<IndicatorBlockProps> = ({ field, indicator }) => { + return ( + <EuiPanel {...panelProps}> + <VisibleOnHover> + <EuiText> + <IndicatorFieldLabel field={field} /> + </EuiText> + <EuiSpacer size="s" /> + <EuiText size="s"> + <IndicatorFieldValue indicator={indicator} field={field} /> + <span className="actionsWrapper"> + <IndicatorValueActions indicator={indicator} field={field} /> + </span> + </EuiText> + </VisibleOnHover> + </EuiPanel> + ); +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/highlighted_values_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/highlighted_values_table.tsx new file mode 100644 index 00000000000000..d7cf25dca3239b --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/highlighted_values_table.tsx @@ -0,0 +1,54 @@ +/* + * 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, { useMemo, VFC } from 'react'; +import { Indicator, RawIndicatorFieldId } from '../../../../../../../../../common/types/indicator'; +import { unwrapValue } from '../../../../../../lib/unwrap_value'; +import { IndicatorFieldsTable } from '../../../../components/indicator_fields_table'; + +/** + * Pick indicator fields starting with the indicator type + */ +const byIndicatorType = (indicatorType: string) => (field: string) => + field.startsWith(`threat.indicator.${indicatorType}`) || + [ + 'threat.indicator.reference', + 'threat.indicator.description', + 'threat.software.alias', + 'threat.indicator.confidence', + 'threat.tactic.name', + 'threat.tactic.reference', + ].includes(field); + +interface HighlightedValuesTableProps { + indicator: Indicator; + ['data-test-subj']?: string; +} + +/** + * Displays highlighted indicator values based on indicator type + */ +export const HighlightedValuesTable: VFC<HighlightedValuesTableProps> = ({ + indicator, + ...props +}) => { + const indicatorType = unwrapValue(indicator, RawIndicatorFieldId.Type); + + const highlightedFields: string[] = useMemo( + () => Object.keys(indicator.fields).filter(byIndicatorType(indicatorType || '')), + [indicator.fields, indicatorType] + ); + + return ( + <IndicatorFieldsTable + search={false} + indicator={indicator} + fields={highlightedFields} + {...props} + /> + ); +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/index.tsx new file mode 100644 index 00000000000000..d31d18ec79367b --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/components/highlighted_values_table/index.tsx @@ -0,0 +1,8 @@ +/* + * 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 './highlighted_values_table'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/index.tsx new file mode 100644 index 00000000000000..71fcb871adf42e --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/index.tsx @@ -0,0 +1,8 @@ +/* + * 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 './indicators_flyout_overview'; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.stories.tsx new file mode 100644 index 00000000000000..72b20f769575b7 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.stories.tsx @@ -0,0 +1,36 @@ +/* + * 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 { Story } from '@storybook/react'; +import { StoryProvidersComponent } from '../../../../../../common/mocks/story_providers'; +import { generateMockIndicator, Indicator } from '../../../../../../../common/types/indicator'; +import { IndicatorsFlyoutOverview } from './indicators_flyout_overview'; +import { IndicatorsFiltersContext } from '../../../../context'; + +export default { + component: IndicatorsFlyoutOverview, + title: 'IndicatorsFlyoutOverview', + parameters: { + backgrounds: { + default: 'white', + values: [{ name: 'white', value: '#fff' }], + }, + }, +}; + +export const Default: Story<void> = () => { + const mockIndicator: Indicator = generateMockIndicator(); + + return ( + <StoryProvidersComponent> + <IndicatorsFiltersContext.Provider value={{} as any}> + <IndicatorsFlyoutOverview onViewAllFieldsInTable={() => {}} indicator={mockIndicator} /> + </IndicatorsFiltersContext.Provider> + </StoryProvidersComponent> + ); +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.test.tsx new file mode 100644 index 00000000000000..580534e5668c20 --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.test.tsx @@ -0,0 +1,48 @@ +/* + * 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 { TestProvidersComponent } from '../../../../../../common/mocks/test_providers'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import { generateMockIndicator, Indicator } from '../../../../../../../common/types/indicator'; +import { + IndicatorsFlyoutOverview, + TI_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS, + TI_FLYOUT_OVERVIEW_TABLE, +} from './indicators_flyout_overview'; +import { EMPTY_PROMPT_TEST_ID } from '../../components/indicator_empty_prompt'; + +describe('<IndicatorsFlyoutOverview />', () => { + describe('invalid indicator', () => { + it('should render error message on invalid indicator', () => { + render( + <TestProvidersComponent> + <IndicatorsFlyoutOverview + onViewAllFieldsInTable={() => {}} + indicator={{ fields: {} } as unknown as Indicator} + /> + </TestProvidersComponent> + ); + + expect(screen.getByTestId(EMPTY_PROMPT_TEST_ID)).toBeInTheDocument(); + }); + }); + + it('should render the highlighted blocks and table when valid indicator is passed', () => { + render( + <TestProvidersComponent> + <IndicatorsFlyoutOverview + onViewAllFieldsInTable={() => {}} + indicator={generateMockIndicator()} + /> + </TestProvidersComponent> + ); + + expect(screen.queryByTestId(TI_FLYOUT_OVERVIEW_TABLE)).toBeInTheDocument(); + expect(screen.queryByTestId(TI_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS)).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.tsx new file mode 100644 index 00000000000000..371af7299b3eae --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_overview/indicators_flyout_overview.tsx @@ -0,0 +1,111 @@ +/* + * 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 { + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React, { useMemo } from 'react'; +import { VFC } from 'react'; +import { EMPTY_VALUE } from '../../../../../../../common/constants'; +import { Indicator, RawIndicatorFieldId } from '../../../../../../../common/types/indicator'; +import { unwrapValue } from '../../../../lib/unwrap_value'; +import { IndicatorEmptyPrompt } from '../../components/indicator_empty_prompt'; +import { IndicatorBlock } from './components/block'; +import { HighlightedValuesTable } from './components/highlighted_values_table'; + +const highLevelFields = [ + RawIndicatorFieldId.Feed, + RawIndicatorFieldId.Type, + RawIndicatorFieldId.MarkingTLP, + RawIndicatorFieldId.Confidence, +]; + +export const TI_FLYOUT_OVERVIEW_TABLE = 'tiFlyoutOverviewTable'; +export const TI_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS = 'tiFlyoutOverviewHighLevelBlocks'; + +export interface IndicatorsFlyoutOverviewProps { + indicator: Indicator; + onViewAllFieldsInTable: VoidFunction; +} + +export const IndicatorsFlyoutOverview: VFC<IndicatorsFlyoutOverviewProps> = ({ + indicator, + onViewAllFieldsInTable, +}) => { + const indicatorType = unwrapValue(indicator, RawIndicatorFieldId.Type); + + const highLevelBlocks = useMemo( + () => ( + <EuiFlexGroup data-test-subj={TI_FLYOUT_OVERVIEW_HIGH_LEVEL_BLOCKS}> + {highLevelFields.map((field) => ( + <EuiFlexItem key={field}> + <IndicatorBlock indicator={indicator} field={field} /> + </EuiFlexItem> + ))} + </EuiFlexGroup> + ), + [indicator] + ); + + const indicatorDescription = useMemo(() => { + const unwrappedDescription = unwrapValue(indicator, RawIndicatorFieldId.Description); + + return unwrappedDescription ? <EuiText>{unwrappedDescription}</EuiText> : null; + }, [indicator]); + + const indicatorName = unwrapValue(indicator, RawIndicatorFieldId.Name) || EMPTY_VALUE; + + if (!indicatorType) { + return <IndicatorEmptyPrompt />; + } + + return ( + <> + <EuiTitle> + <h2>{indicatorName}</h2> + </EuiTitle> + + {indicatorDescription} + + <EuiSpacer /> + + {highLevelBlocks} + + <EuiHorizontalRule /> + + <EuiFlexGroup> + <EuiFlexItem> + <EuiTitle size="xxs"> + <h5> + <FormattedMessage + id="xpack.threatIntelligence.indicator.flyoutOverviewTable.highlightedFields" + defaultMessage="Highlighted fields" + /> + </h5> + </EuiTitle> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <EuiButtonEmpty onClick={onViewAllFieldsInTable}> + <FormattedMessage + id="xpack.threatIntelligence.indicator.flyoutOverviewTable.viewAllFieldsInTable" + defaultMessage="View all fields in table" + /> + </EuiButtonEmpty> + </EuiFlexItem> + </EuiFlexGroup> + + <HighlightedValuesTable indicator={indicator} data-test-subj={TI_FLYOUT_OVERVIEW_TABLE} /> + </> + ); +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/index.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/index.tsx similarity index 100% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/index.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/index.tsx diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.stories.tsx similarity index 62% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.stories.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.stories.tsx index e864d292c61cb1..3a3aa1fa788ee1 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.stories.tsx @@ -9,13 +9,12 @@ import React from 'react'; import { Story } from '@storybook/react'; import { CoreStart } from '@kbn/core/public'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; -import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indicators_filters_context'; -import { generateFieldTypeMap } from '../../../../common/mocks/mock_field_type_map'; -import { mockUiSettingsService } from '../../../../common/mocks/mock_kibana_ui_settings_service'; -import { mockKibanaTimelinesService } from '../../../../common/mocks/mock_kibana_timelines_service'; -import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; +import { mockIndicatorsFiltersContext } from '../../../../../../common/mocks/mock_indicators_filters_context'; +import { mockUiSettingsService } from '../../../../../../common/mocks/mock_kibana_ui_settings_service'; +import { mockKibanaTimelinesService } from '../../../../../../common/mocks/mock_kibana_timelines_service'; +import { generateMockIndicator, Indicator } from '../../../../../../../common/types/indicator'; import { IndicatorsFlyoutTable } from './indicators_flyout_table'; -import { IndicatorsFiltersContext } from '../../context'; +import { IndicatorsFiltersContext } from '../../../../context'; export default { component: IndicatorsFlyoutTable, @@ -24,7 +23,6 @@ export default { export const Default: Story<void> = () => { const mockIndicator: Indicator = generateMockIndicator(); - const mockFieldTypesMap = generateFieldTypeMap(); const KibanaReactContext = createKibanaReactContext({ uiSettings: mockUiSettingsService(), @@ -34,14 +32,12 @@ export const Default: Story<void> = () => { return ( <KibanaReactContext.Provider> <IndicatorsFiltersContext.Provider value={mockIndicatorsFiltersContext}> - <IndicatorsFlyoutTable indicator={mockIndicator} fieldTypesMap={mockFieldTypesMap} /> + <IndicatorsFlyoutTable indicator={mockIndicator} /> </IndicatorsFiltersContext.Provider> </KibanaReactContext.Provider> ); }; export const EmptyIndicator: Story<void> = () => { - return ( - <IndicatorsFlyoutTable indicator={{ fields: {} } as unknown as Indicator} fieldTypesMap={{}} /> - ); + return <IndicatorsFlyoutTable indicator={{ fields: {} } as unknown as Indicator} />; }; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.test.tsx similarity index 72% rename from x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.test.tsx rename to x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.test.tsx index bc7cfffbcf7a31..c91ce0e6aa89c8 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.test.tsx @@ -7,28 +7,23 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; +import { TestProvidersComponent } from '../../../../../../common/mocks/test_providers'; import { generateMockIndicator, Indicator, RawIndicatorFieldId, -} from '../../../../../common/types/indicator'; -import { generateFieldTypeMap } from '../../../../common/mocks/mock_field_type_map'; -import { - EMPTY_PROMPT_TEST_ID, - IndicatorsFlyoutTable, - TABLE_TEST_ID, -} from './indicators_flyout_table'; -import { unwrapValue } from '../../lib/unwrap_value'; +} from '../../../../../../../common/types/indicator'; +import { IndicatorsFlyoutTable, TABLE_TEST_ID } from './indicators_flyout_table'; +import { unwrapValue } from '../../../../lib/unwrap_value'; +import { EMPTY_PROMPT_TEST_ID } from '../../components/indicator_empty_prompt'; const mockIndicator: Indicator = generateMockIndicator(); -const mockFieldTypesMap = generateFieldTypeMap(); describe('<IndicatorsFlyoutTable />', () => { it('should render fields and values in table', () => { const { getByTestId, getByText, getAllByText } = render( <TestProvidersComponent> - <IndicatorsFlyoutTable indicator={mockIndicator} fieldTypesMap={mockFieldTypesMap} /> + <IndicatorsFlyoutTable indicator={mockIndicator} /> </TestProvidersComponent> ); @@ -49,7 +44,7 @@ describe('<IndicatorsFlyoutTable />', () => { it('should render error message on invalid indicator', () => { const { getByTestId, getByText } = render( <TestProvidersComponent> - <IndicatorsFlyoutTable indicator={{ fields: {} }} fieldTypesMap={{}} /> + <IndicatorsFlyoutTable indicator={{ fields: {} }} /> </TestProvidersComponent> ); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.tsx new file mode 100644 index 00000000000000..83bd913e3eedba --- /dev/null +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout/tabs/indicators_flyout_table/indicators_flyout_table.tsx @@ -0,0 +1,47 @@ +/* + * 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, { VFC } from 'react'; +import { Indicator } from '../../../../../../../common/types/indicator'; +import { IndicatorEmptyPrompt } from '../../components/indicator_empty_prompt'; +import { IndicatorFieldsTable } from '../../components/indicator_fields_table'; + +export const TABLE_TEST_ID = 'tiFlyoutTableMemoryTable'; +export const TIMELINE_BUTTON_TEST_ID = 'tiFlyoutTableRowTimelineButton'; + +const search = { + box: { + incremental: true, + schema: true, + }, +}; + +export interface IndicatorsFlyoutTableProps { + /** + * Indicator to display in table view. + */ + indicator: Indicator; +} + +/** + * Displays all the properties and values of an {@link Indicator} in table view, + * using the {@link EuiInMemoryTable} from the @elastic/eui library. + */ +export const IndicatorsFlyoutTable: VFC<IndicatorsFlyoutTableProps> = ({ indicator }) => { + const items: string[] = Object.keys(indicator.fields); + + return items.length === 0 ? ( + <IndicatorEmptyPrompt /> + ) : ( + <IndicatorFieldsTable + data-test-subj={TABLE_TEST_ID} + search={search} + fields={items} + indicator={indicator} + /> + ); +}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.tsx deleted file mode 100644 index c6a64c51629afb..00000000000000 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_flyout_table/indicators_flyout_table.tsx +++ /dev/null @@ -1,120 +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 { EuiEmptyPrompt, EuiInMemoryTable } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import React, { VFC } from 'react'; -import { FilterInOut } from '../../../query_bar/components/filter_in_out'; -import { Indicator } from '../../../../../common/types/indicator'; -import { AddToTimeline } from '../../../timeline/components/add_to_timeline'; -import { IndicatorField } from '../indicator_field/indicator_field'; - -export const EMPTY_PROMPT_TEST_ID = 'tiFlyoutTableEmptyPrompt'; -export const TABLE_TEST_ID = 'tiFlyoutTableMemoryTable'; -export const TIMELINE_BUTTON_TEST_ID = 'tiFlyoutTableRowTimelineButton'; - -const search = { - box: { - incremental: true, - schema: true, - }, -}; - -export interface IndicatorsFlyoutTableProps { - /** - * Indicator to display in table view. - */ - indicator: Indicator; - /** - * Object mapping each field with their type to ease display in the {@link IndicatorField} component. - */ - fieldTypesMap: { [id: string]: string }; -} - -/** - * Displays all the properties and values of an {@link Indicator} in table view, - * using the {@link EuiInMemoryTable} from the @elastic/eui library. - */ -export const IndicatorsFlyoutTable: VFC<IndicatorsFlyoutTableProps> = ({ - indicator, - fieldTypesMap, -}) => { - const items: string[] = Object.keys(indicator.fields); - const columns = [ - { - name: ( - <FormattedMessage - id="xpack.threatIntelligence.indicator.flyoutTable.actionsColumnLabel" - defaultMessage="Actions" - /> - ), - actions: [ - { - render: (field: string) => ( - <> - <FilterInOut data={indicator} field={field} /> - <AddToTimeline data={indicator} field={field} testId={TIMELINE_BUTTON_TEST_ID} /> - </> - ), - }, - ], - width: '72px', - }, - { - name: ( - <FormattedMessage - id="xpack.threatIntelligence.indicator.flyoutTable.fieldColumnLabel" - defaultMessage="Field" - /> - ), - render: (field: string) => field, - }, - { - name: ( - <FormattedMessage - id="xpack.threatIntelligence.indicator.flyoutTable.valueColumnLabel" - defaultMessage="Value" - /> - ), - render: (field: string) => ( - <IndicatorField indicator={indicator} field={field} fieldTypesMap={fieldTypesMap} /> - ), - }, - ]; - - return items.length === 0 ? ( - <EuiEmptyPrompt - iconType="alert" - color="danger" - title={ - <h2> - <FormattedMessage - id="xpack.threatIntelligence.indicator.flyoutTable.errorMessageTitle" - defaultMessage="Unable to display indicator information" - /> - </h2> - } - body={ - <p> - <FormattedMessage - id="xpack.threatIntelligence.indicator.flyoutTable.errorMessageBody" - defaultMessage="There was an error displaying the indicator fields and values." - /> - </p> - } - data-test-subj={EMPTY_PROMPT_TEST_ID} - /> - ) : ( - <EuiInMemoryTable - items={items} - columns={columns} - search={search} - sorting={true} - data-test-subj={TABLE_TEST_ID} - /> - ); -}; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_actions.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_actions.tsx index db3de2eeb67e77..c17d09a4bf7dc1 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_actions.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_actions.tsx @@ -50,11 +50,11 @@ export const CellActions: VFC<CellActionsProps> = ({ return ( <> - <FilterInOut Component={Component} data={indicator} field={key} /> + <FilterInOut as={Component} data={indicator} field={key} /> <AddToTimeline data={indicator} field={key} - component={Component} + as={Component} testId={CELL_TIMELINE_BUTTON_TEST_ID} /> </> diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_renderer.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_renderer.tsx index e0b4e1e88daa04..b95a378a35a5b2 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_renderer.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/cell_renderer.tsx @@ -11,7 +11,7 @@ import { euiLightVars as themeLight, euiDarkVars as themeDark } from '@kbn/ui-th import React from 'react'; import { useKibana } from '../../../../hooks/use_kibana'; import { Indicator } from '../../../../../common/types/indicator'; -import { IndicatorField } from '../indicator_field/indicator_field'; +import { IndicatorFieldValue } from '../indicator_field_value/indicator_field_value'; import { IndicatorsTableContext } from './context'; import { ActionsRowCell } from './actions_row_cell'; @@ -29,7 +29,7 @@ export const cellRendererFactory = (from: number) => { const darkMode = uiSettings.get('theme:darkMode'); - const { indicators, expanded, fieldTypesMap } = indicatorsTableContext; + const { indicators, expanded } = indicatorsTableContext; const indicator: Indicator | undefined = indicators[rowIndex - from]; @@ -53,6 +53,6 @@ export const cellRendererFactory = (from: number) => { return <ActionsRowCell indicator={indicator} />; } - return <IndicatorField indicator={indicator} field={columnId} fieldTypesMap={fieldTypesMap} />; + return <IndicatorFieldValue indicator={indicator} field={columnId} />; }; }; diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/context.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/context.ts index bd8c619edfd040..41596a257dc9e6 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/context.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/context.ts @@ -12,7 +12,6 @@ export interface IndicatorsTableContextValue { expanded: Indicator | undefined; setExpanded: Dispatch<SetStateAction<Indicator | undefined>>; indicators: Indicator[]; - fieldTypesMap: { [id: string]: string }; } export const IndicatorsTableContext = createContext<IndicatorsTableContextValue | undefined>( diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/hooks/use_column_settings.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/hooks/use_column_settings.ts index 266ef8811955d0..8315f41725ed0c 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/hooks/use_column_settings.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/hooks/use_column_settings.ts @@ -7,52 +7,22 @@ import { EuiDataGridColumn } from '@elastic/eui'; import { useCallback, useEffect, useMemo, useState } from 'react'; -import { i18n } from '@kbn/i18n'; import negate from 'lodash/negate'; import { RawIndicatorFieldId } from '../../../../../../common/types/indicator'; import { useKibana } from '../../../../../hooks/use_kibana'; +import { translateFieldLabel } from '../../indicator_field_label'; const DEFAULT_COLUMNS: EuiDataGridColumn[] = [ - { - id: RawIndicatorFieldId.TimeStamp, - displayAsText: i18n.translate('xpack.threatIntelligence.indicator.table.timestampColumnTitle', { - defaultMessage: '@timestamp', - }), - }, - { - id: RawIndicatorFieldId.Name, - displayAsText: i18n.translate('xpack.threatIntelligence.indicator.table.indicatorColumTitle', { - defaultMessage: 'Indicator', - }), - }, - { - id: RawIndicatorFieldId.Type, - displayAsText: i18n.translate( - 'xpack.threatIntelligence.indicator.table.indicatorTypeColumTitle', - { - defaultMessage: 'Indicator type', - } - ), - }, - { - id: RawIndicatorFieldId.Feed, - displayAsText: i18n.translate('xpack.threatIntelligence.indicator.table.FeedColumTitle', { - defaultMessage: 'Feed', - }), - }, - { - id: RawIndicatorFieldId.FirstSeen, - displayAsText: i18n.translate('xpack.threatIntelligence.indicator.table.firstSeenColumTitle', { - defaultMessage: 'First seen', - }), - }, - { - id: RawIndicatorFieldId.LastSeen, - displayAsText: i18n.translate('xpack.threatIntelligence.indicator.table.lastSeenColumTitle', { - defaultMessage: 'Last seen', - }), - }, -]; + RawIndicatorFieldId.TimeStamp, + RawIndicatorFieldId.Name, + RawIndicatorFieldId.Type, + RawIndicatorFieldId.Feed, + RawIndicatorFieldId.FirstSeen, + RawIndicatorFieldId.LastSeen, +].map((field) => ({ + id: field, + displayAsText: translateFieldLabel(field), +})); const DEFAULT_VISIBLE_COLUMNS = DEFAULT_COLUMNS.map((column) => column.id); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.stories.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.stories.tsx index e92df3f388e97b..07765dbf601d4d 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.stories.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.stories.tsx @@ -5,14 +5,10 @@ * 2.0. */ -import { CoreStart } from '@kbn/core/public'; -import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; import React from 'react'; import { DataView } from '@kbn/data-views-plugin/common'; import { mockIndicatorsFiltersContext } from '../../../../common/mocks/mock_indicators_filters_context'; -import { mockTriggersActionsUiService } from '../../../../common/mocks/mock_kibana_triggers_actions_ui_service'; -import { mockUiSettingsService } from '../../../../common/mocks/mock_kibana_ui_settings_service'; -import { mockKibanaTimelinesService } from '../../../../common/mocks/mock_kibana_timelines_service'; +import { StoryProvidersComponent } from '../../../../common/mocks/story_providers'; import { generateMockIndicator, Indicator } from '../../../../../common/types/indicator'; import { IndicatorsTable } from './indicators_table'; import { IndicatorsFiltersContext } from '../../context'; @@ -29,14 +25,8 @@ const stub = () => void 0; export function WithIndicators() { const indicatorsFixture: Indicator[] = Array(10).fill(generateMockIndicator()); - const KibanaReactContext = createKibanaReactContext({ - uiSettings: mockUiSettingsService(), - timelines: mockKibanaTimelinesService, - triggersActionsUi: mockTriggersActionsUiService, - } as unknown as CoreStart); - return ( - <KibanaReactContext.Provider> + <StoryProvidersComponent> <IndicatorsFiltersContext.Provider value={mockIndicatorsFiltersContext}> <IndicatorsTable browserFields={{}} @@ -53,25 +43,27 @@ export function WithIndicators() { indexPattern={mockIndexPattern} /> </IndicatorsFiltersContext.Provider> - </KibanaReactContext.Provider> + </StoryProvidersComponent> ); } export function WithNoIndicators() { return ( - <IndicatorsTable - browserFields={{}} - pagination={{ - pageSize: 10, - pageIndex: 0, - pageSizeOptions: [10, 25, 50], - }} - indicators={[]} - onChangePage={stub} - onChangeItemsPerPage={stub} - indicatorCount={0} - loading={false} - indexPattern={mockIndexPattern} - /> + <StoryProvidersComponent> + <IndicatorsTable + browserFields={{}} + pagination={{ + pageSize: 10, + pageIndex: 0, + pageSizeOptions: [10, 25, 50], + }} + indicators={[]} + onChangePage={stub} + onChangeItemsPerPage={stub} + indicatorCount={0} + loading={false} + indexPattern={mockIndexPattern} + /> + </StoryProvidersComponent> ); } diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx index 9cd711d313a542..a3604b31cf75d4 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/components/indicators_table/indicators_table.tsx @@ -55,7 +55,6 @@ export const IndicatorsTable: VFC<IndicatorsTableProps> = ({ onChangeItemsPerPage, pagination, loading, - indexPattern, browserFields, }) => { const [expanded, setExpanded] = useState<Indicator>(); @@ -65,18 +64,9 @@ export const IndicatorsTable: VFC<IndicatorsTableProps> = ({ [pagination.pageIndex, pagination.pageSize] ); - // field name to field type map to allow the cell_renderer to format dates - const fieldTypesMap: { [id: string]: string } = useMemo(() => { - if (!indexPattern) return {}; - - const res: { [id: string]: string } = {}; - indexPattern.fields.map((field) => (res[field.name] = field.type)); - return res; - }, [indexPattern]); - const indicatorTableContextValue = useMemo<IndicatorsTableContextValue>( - () => ({ expanded, setExpanded, indicators, fieldTypesMap }), - [expanded, indicators, fieldTypesMap] + () => ({ expanded, setExpanded, indicators }), + [expanded, indicators] ); const start = pagination.pageIndex * pagination.pageSize; @@ -131,13 +121,9 @@ export const IndicatorsTable: VFC<IndicatorsTableProps> = ({ const flyoutFragment = useMemo( () => expanded ? ( - <IndicatorsFlyout - indicator={expanded} - fieldTypesMap={fieldTypesMap} - closeFlyout={() => setExpanded(undefined)} - /> + <IndicatorsFlyout indicator={expanded} closeFlyout={() => setExpanded(undefined)} /> ) : null, - [expanded, fieldTypesMap] + [expanded] ); const gridFragment = useMemo(() => { diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts index 9ea7e492c7893d..82e59dc7b3ad33 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_aggregated_indicators.ts @@ -197,12 +197,12 @@ export const useAggregatedIndicators = ({ ) .subscribe({ next: (response) => { - const aggregations: Aggregation[] = - response.rawResponse.aggregations[AGGREGATION_NAME]?.buckets; - const chartSeries: ChartSeries[] = convertAggregationToChartSeries(aggregations); - setIndicators(chartSeries); - if (isCompleteResponse(response)) { + const aggregations: Aggregation[] = + response.rawResponse.aggregations[AGGREGATION_NAME]?.buckets; + const chartSeries: ChartSeries[] = convertAggregationToChartSeries(aggregations); + setIndicators(chartSeries); + searchSubscription$.current.unsubscribe(); } else if (isErrorResponse(response)) { searchSubscription$.current.unsubscribe(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.tsx index f492ac74dcaa37..c3b643df2ec456 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/indicators_page.tsx @@ -15,6 +15,7 @@ import { useFilters } from '../query_bar/hooks/use_filters'; import { FiltersGlobal } from '../../containers/filters_global'; import QueryBar from '../query_bar/components/query_bar'; import { useSourcererDataView } from './hooks/use_sourcerer_data_view'; +import { FieldTypesProvider } from '../../containers/field_types_provider'; export const IndicatorsPage: VFC = () => { const { browserFields, indexPattern } = useSourcererDataView(); @@ -37,33 +38,35 @@ export const IndicatorsPage: VFC = () => { }); return ( - <DefaultPageLayout pageTitle="Indicators"> - <FiltersGlobal> - <QueryBar - dateRangeFrom={timeRange?.from} - dateRangeTo={timeRange?.to} - indexPattern={indexPattern} - filterQuery={filterQuery} - filterManager={filterManager} - filters={filters} - dataTestSubj="iocListPageQueryInput" - displayStyle="detached" - savedQuery={savedQuery} - onRefresh={handleRefresh} - onSubmitQuery={handleSubmitQuery} - onSavedQuery={handleSavedQuery} - onSubmitDateRange={handleSubmitTimeRange} - /> - </FiltersGlobal> - <IndicatorsFilters filterManager={filterManager}> - <IndicatorsBarChartWrapper timeRange={timeRange} indexPattern={indexPattern} /> - <IndicatorsTable - {...indicators} - browserFields={browserFields} - indexPattern={indexPattern} - /> - </IndicatorsFilters> - </DefaultPageLayout> + <FieldTypesProvider> + <DefaultPageLayout pageTitle="Indicators"> + <FiltersGlobal> + <QueryBar + dateRangeFrom={timeRange?.from} + dateRangeTo={timeRange?.to} + indexPattern={indexPattern} + filterQuery={filterQuery} + filterManager={filterManager} + filters={filters} + dataTestSubj="iocListPageQueryInput" + displayStyle="detached" + savedQuery={savedQuery} + onRefresh={handleRefresh} + onSubmitQuery={handleSubmitQuery} + onSavedQuery={handleSavedQuery} + onSubmitDateRange={handleSubmitTimeRange} + /> + </FiltersGlobal> + <IndicatorsFilters filterManager={filterManager}> + <IndicatorsBarChartWrapper timeRange={timeRange} indexPattern={indexPattern} /> + <IndicatorsTable + {...indicators} + browserFields={browserFields} + indexPattern={indexPattern} + /> + </IndicatorsFilters> + </DefaultPageLayout> + </FieldTypesProvider> ); }; diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.test.tsx index db11ca497b5156..71de0fe1e6ab8d 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.test.tsx @@ -38,7 +38,7 @@ describe('<FilterInOut />', () => { const mockComponent: FunctionComponent = () => <EuiButtonIcon iconType="plusInCircle" />; const component = render( - <FilterInOut data={mockIndicator} field={mockField} Component={mockComponent} /> + <FilterInOut data={mockIndicator} field={mockField} as={mockComponent} /> ); expect(component).toMatchSnapshot(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.tsx index 56088c953ef08c..0027758505fff1 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/filter_in_out/filter_in_out.tsx @@ -42,13 +42,13 @@ export interface FilterInOutProps { /** * Display component for when the FilterIn component is used within a DataGrid */ - Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon; + as?: typeof EuiButtonEmpty | typeof EuiButtonIcon; } /** * Retrieves the indicator's field and value, then creates a new {@link Filter} and adds it to the {@link FilterManager}. */ -export const FilterInOut: VFC<FilterInOutProps> = ({ data, field, Component }) => { +export const FilterInOut: VFC<FilterInOutProps> = ({ data, field, as: Component }) => { const styles = useStyles(); const { filterManager } = useIndicatorsFiltersContext(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx index c677a7613e3e62..4a2bbe9be6367a 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/timeline/components/add_to_timeline/add_to_timeline.tsx @@ -27,7 +27,7 @@ export interface AddToTimelineProps { /** * Only used with `EuiDataGrid` (see {@link AddToTimelineButtonProps}). */ - component?: typeof EuiButtonEmpty | typeof EuiButtonIcon; + as?: typeof EuiButtonEmpty | typeof EuiButtonIcon; /** * Used as `data-test-subj` value for e2e tests. */ @@ -42,7 +42,7 @@ export interface AddToTimelineProps { * * @returns add to timeline button or an empty component. */ -export const AddToTimeline: VFC<AddToTimelineProps> = ({ data, field, component, testId }) => { +export const AddToTimeline: VFC<AddToTimelineProps> = ({ data, field, as, testId }) => { const styles = useStyles(); const addToTimelineButton = @@ -78,7 +78,7 @@ export const AddToTimeline: VFC<AddToTimelineProps> = ({ data, field, component, field: key, ownFocus: false, }; - if (component) addToTimelineProps.Component = component; + if (as) addToTimelineProps.Component = as; return ( <div data-test-subj={testId} css={styles.button}> diff --git a/x-pack/plugins/threat_intelligence/scripts/generate_indicators.js b/x-pack/plugins/threat_intelligence/scripts/generate_indicators.js index bade9615b630d7..44e0ad166353c4 100644 --- a/x-pack/plugins/threat_intelligence/scripts/generate_indicators.js +++ b/x-pack/plugins/threat_intelligence/scripts/generate_indicators.js @@ -8,7 +8,7 @@ const { Client } = require('@elastic/elasticsearch'); const faker = require('faker'); -const THREAT_INDEX = 'ti-logs'; +const THREAT_INDEX = 'logs-ti'; /** Drop the index first? */ const CLEANUP_FIRST = true; @@ -82,7 +82,7 @@ const main = async () => { for (let i = 0; i < CHUNK_SIZE; i++) { const RANDOM_OFFSET_WITHIN_ONE_MONTH = Math.floor(Math.random() * 3600 * 24 * 30 * 1000); - const timestamp = Date.now() - RANDOM_OFFSET_WITHIN_ONE_MONTH; + const timestamp = new Date(Date.now() - RANDOM_OFFSET_WITHIN_ONE_MONTH).toISOString(); operations.push( ...[ diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index a7aadfb61248ad..01bbf59adb16fc 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -31395,7 +31395,6 @@ "xpack.synthetics.uptimeSettings.index": "Paramètres Uptime - Index", "xpack.synthetics.waterfallChart.sidebar.url.https": "https", "xpack.threatIntelligence.common.emptyPage.body3": "Pour vous lancer avec Elastic Threat Intelligence, activez une ou plusieurs intégrations Threat Intelligence depuis la page Intégrations ou bien ingérez des données avec Filebeat. Pour plus d'informations, consultez la ressource {docsLink}.", - "xpack.threatIntelligence.indicator.flyout.panelTitle": "Indicateur : {title}", "xpack.threatIntelligence.common.emptyPage.body1": "Elastic Threat Intelligence facilite l'analyse et l'investigation des menaces potentielles pour la sécurité en regroupant les données de plusieurs sources en un seul endroit.", "xpack.threatIntelligence.common.emptyPage.body2": "Vous pourrez consulter les données de tous les flux Threat Intelligence activés et prendre des mesures à partir de cette page.", "xpack.threatIntelligence.common.emptyPage.buttonText": "Ajouter des intégrations", @@ -31406,18 +31405,16 @@ "xpack.threatIntelligence.empty.title": "Aucun résultat ne correspond à vos critères de recherche.", "xpack.threatIntelligence.indicator.flyout.jsonTabLabel": "JSON", "xpack.threatIntelligence.indicator.flyout.tableTabLabel": "Tableau", - "xpack.threatIntelligence.indicator.flyoutJson.errorMessageBody": "Une erreur s'est produite lors de l'affichage des champs et des valeurs des indicateurs.", - "xpack.threatIntelligence.indicator.flyoutJson.errorMessageTitle": "Impossible d'afficher les informations des indicateurs", "xpack.threatIntelligence.indicator.flyoutTable.errorMessageBody": "Une erreur s'est produite lors de l'affichage des champs et des valeurs des indicateurs.", "xpack.threatIntelligence.indicator.flyoutTable.errorMessageTitle": "Impossible d'afficher les informations des indicateurs", - "xpack.threatIntelligence.indicator.flyoutTable.fieldColumnLabel": "Champ", - "xpack.threatIntelligence.indicator.flyoutTable.valueColumnLabel": "Valeur", + "xpack.threatIntelligence.indicator.fieldsTable.fieldColumnLabel": "Champ", + "xpack.threatIntelligence.indicator.fieldsTable.valueColumnLabel": "Valeur", "xpack.threatIntelligence.indicator.table.actionColumnLabel": "Actions", - "xpack.threatIntelligence.indicator.table.FeedColumTitle": "Fil", - "xpack.threatIntelligence.indicator.table.firstSeenColumTitle": "Vu en premier", - "xpack.threatIntelligence.indicator.table.indicatorColumTitle": "Indicateur", - "xpack.threatIntelligence.indicator.table.indicatorTypeColumTitle": "Type d’indicateur", - "xpack.threatIntelligence.indicator.table.lastSeenColumTitle": "Vu en dernier", + "xpack.threatIntelligence.field.threat.feed.name": "Fil", + "xpack.threatIntelligence.field.threat.indicator.first_seen": "Vu en premier", + "xpack.threatIntelligence.field.threat.indicator.name": "Indicateur", + "xpack.threatIntelligence.field.threat.indicator.type": "Type d’indicateur", + "xpack.threatIntelligence.field.threat.indicator.last_seen": "Vu en dernier", "xpack.threatIntelligence.indicator.table.viewDetailsButton": "Afficher les détails", "xpack.timelines.clipboard.copy.successToastTitle": "Champ {field} copié dans le presse-papiers", "xpack.timelines.footer.autoRefreshActiveTooltip": "Lorsque l'actualisation automatique est activée, la chronologie vous montrera les {numberOfItems} derniers événements correspondant à votre recherche.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index fd4a320e417e14..f6dbbfc7358904 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -31373,7 +31373,6 @@ "xpack.synthetics.uptimeSettings.index": "アップタイム設定 - インデックス", "xpack.synthetics.waterfallChart.sidebar.url.https": "https", "xpack.threatIntelligence.common.emptyPage.body3": "Elastic Threat Intelligenceを開始するには、[統合]ページから1つ以上の脅威インテリジェンス統合を有効にするか、Filebeatを使用してデータを取り込みます。詳細については、{docsLink}をご覧ください。", - "xpack.threatIntelligence.indicator.flyout.panelTitle": "インジケーター:{title}", "xpack.threatIntelligence.common.emptyPage.body1": "Elastic Threat Intelligenceでは、複数のソースのデータを一元的に集約することで、潜在的なセキュリティ脅威を簡単に分析、調査できます。", "xpack.threatIntelligence.common.emptyPage.body2": "すべてのアクティブな脅威インテリジェンスフィードのデータを表示し、このページからアクションを実行できます。", "xpack.threatIntelligence.common.emptyPage.buttonText": "統合の追加", @@ -31384,18 +31383,16 @@ "xpack.threatIntelligence.empty.title": "検索条件と一致する結果がありません。", "xpack.threatIntelligence.indicator.flyout.jsonTabLabel": "JSON", "xpack.threatIntelligence.indicator.flyout.tableTabLabel": "表", - "xpack.threatIntelligence.indicator.flyoutJson.errorMessageBody": "インジケーターフィールドと値の表示エラーが発生しました。", - "xpack.threatIntelligence.indicator.flyoutJson.errorMessageTitle": "インジケーター情報を表示できませn", "xpack.threatIntelligence.indicator.flyoutTable.errorMessageBody": "インジケーターフィールドと値の表示エラーが発生しました。", "xpack.threatIntelligence.indicator.flyoutTable.errorMessageTitle": "インジケーター情報を表示できませn", - "xpack.threatIntelligence.indicator.flyoutTable.fieldColumnLabel": "フィールド", - "xpack.threatIntelligence.indicator.flyoutTable.valueColumnLabel": "値", + "xpack.threatIntelligence.indicator.fieldsTable.fieldColumnLabel": "フィールド", + "xpack.threatIntelligence.indicator.fieldsTable.valueColumnLabel": "値", "xpack.threatIntelligence.indicator.table.actionColumnLabel": "アクション", - "xpack.threatIntelligence.indicator.table.FeedColumTitle": "フィード", - "xpack.threatIntelligence.indicator.table.firstSeenColumTitle": "初回の認識", - "xpack.threatIntelligence.indicator.table.indicatorColumTitle": "インジケーター", - "xpack.threatIntelligence.indicator.table.indicatorTypeColumTitle": "インジケータータイプ", - "xpack.threatIntelligence.indicator.table.lastSeenColumTitle": "前回の認識", + "xpack.threatIntelligence.field.threat.feed.name": "フィード", + "xpack.threatIntelligence.field.threat.indicator.first_seen": "初回の認識", + "xpack.threatIntelligence.field.threat.indicator.name": "インジケーター", + "xpack.threatIntelligence.field.threat.indicator.type": "インジケータータイプ", + "xpack.threatIntelligence.field.threat.indicator.last_seen": "前回の認識", "xpack.threatIntelligence.indicator.table.viewDetailsButton": "詳細を表示", "xpack.timelines.clipboard.copy.successToastTitle": "フィールド{field}をクリップボードにコピーしました", "xpack.timelines.footer.autoRefreshActiveTooltip": "自動更新が有効な間、タイムラインはクエリに一致する最新の {numberOfItems} 件のイベントを表示します。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 8002605d93758e..60c556135b465b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -31405,7 +31405,6 @@ "xpack.synthetics.uptimeSettings.index": "Uptime 设置 - 索引", "xpack.synthetics.waterfallChart.sidebar.url.https": "https", "xpack.threatIntelligence.common.emptyPage.body3": "要开始使用 Elastic 威胁情报,请从“集成”页面启用一个或多个威胁情报集成,或使用 Filebeat 采集数据。有关更多信息,请查看 {docsLink}。", - "xpack.threatIntelligence.indicator.flyout.panelTitle": "指标:{title}", "xpack.threatIntelligence.common.emptyPage.body1": "利用 Elastic 威胁情报,可以通过将多个来源的数据聚合到一个位置,轻松分析和调查潜在的安全威胁。", "xpack.threatIntelligence.common.emptyPage.body2": "您将可以查看来自所有已激活威胁情报馈送的数据,并从此页面执行操作。", "xpack.threatIntelligence.common.emptyPage.buttonText": "添加集成", @@ -31416,18 +31415,16 @@ "xpack.threatIntelligence.empty.title": "没有任何结果匹配您的搜索条件", "xpack.threatIntelligence.indicator.flyout.jsonTabLabel": "JSON", "xpack.threatIntelligence.indicator.flyout.tableTabLabel": "表", - "xpack.threatIntelligence.indicator.flyoutJson.errorMessageBody": "显示指标字段和值时出现错误。", - "xpack.threatIntelligence.indicator.flyoutJson.errorMessageTitle": "无法显示指标信息", "xpack.threatIntelligence.indicator.flyoutTable.errorMessageBody": "显示指标字段和值时出现错误。", "xpack.threatIntelligence.indicator.flyoutTable.errorMessageTitle": "无法显示指标信息", - "xpack.threatIntelligence.indicator.flyoutTable.fieldColumnLabel": "字段", - "xpack.threatIntelligence.indicator.flyoutTable.valueColumnLabel": "值", + "xpack.threatIntelligence.indicator.fieldsTable.fieldColumnLabel": "字段", + "xpack.threatIntelligence.indicator.fieldsTable.valueColumnLabel": "值", "xpack.threatIntelligence.indicator.table.actionColumnLabel": "操作", - "xpack.threatIntelligence.indicator.table.FeedColumTitle": "馈送", - "xpack.threatIntelligence.indicator.table.firstSeenColumTitle": "首次看到时间", - "xpack.threatIntelligence.indicator.table.indicatorColumTitle": "指标", - "xpack.threatIntelligence.indicator.table.indicatorTypeColumTitle": "指标类型", - "xpack.threatIntelligence.indicator.table.lastSeenColumTitle": "最后看到时间", + "xpack.threatIntelligence.field.threat.feed.name": "馈送", + "xpack.threatIntelligence.field.threat.indicator.first_seen": "首次看到时间", + "xpack.threatIntelligence.field.threat.indicator.name": "指标", + "xpack.threatIntelligence.field.threat.indicator.type": "指标类型", + "xpack.threatIntelligence.field.threat.indicator.last_seen": "最后看到时间", "xpack.threatIntelligence.indicator.table.viewDetailsButton": "查看详情", "xpack.timelines.clipboard.copy.successToastTitle": "已将字段 {field} 复制到剪贴板", "xpack.timelines.footer.autoRefreshActiveTooltip": "自动刷新已启用时,时间线将显示匹配查询的最近 {numberOfItems} 个事件。", From 0a03f8582fb8635984879fed3257ea8e04e9efa0 Mon Sep 17 00:00:00 2001 From: Klim Markelov <klim.markelov@gmail.com> Date: Tue, 13 Sep 2022 13:55:08 +0200 Subject: [PATCH 102/144] [Enterprise Search][Behavioural Analytics] Introduce Analytics Collection View page (#140421) * Introduce analytics collection view pages * Clean up collection events deletion functionality * Change COLLECTION_VIEW_PATH route * Apply code change requests --- ...ete_analytics_collection_api_logic.test.ts | 33 +++ .../delete_analytics_collection_api_logic.tsx | 24 +++ ...tch_analytics_collection_api_logic.test.ts | 33 +++ .../fetch_analytics_collection_api_logic.tsx | 26 +++ .../add_analytics_collection_logic.test.ts | 2 +- .../add_analytics_collection_logic.ts | 1 + .../analytics_collection_integrate.test.tsx | 35 ++++ .../analytics_collection_integrate.tsx | 121 +++++++++++ .../analytics_collection_settings.test.tsx | 51 +++++ .../analytics_collection_settings.tsx | 99 +++++++++ .../analytics_collection_view.test.tsx | 68 +++++++ .../analytics_collection_view.tsx | 189 ++++++++++++++++++ .../delete_analytics_collection_logic.test.ts | 84 ++++++++ .../delete_analytics_collection_logic.ts | 73 +++++++ .../fetch_analytics_collection_logic.test.tsx | 73 +++++++ .../fetch_analytics_collection_logic.ts | 57 ++++++ .../analytics_collection_table.test.tsx | 2 +- .../analytics_collection_table.tsx | 2 + .../public/applications/analytics/index.tsx | 6 +- .../public/applications/analytics/routes.ts | 2 +- .../delete_analytics_collection.test.ts | 18 +- .../analytics/delete_analytics_collection.ts | 13 -- 22 files changed, 978 insertions(+), 34 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.test.ts new file mode 100644 index 00000000000000..1ad6c18fea3bf8 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.test.ts @@ -0,0 +1,33 @@ +/* + * 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 { mockHttpValues } from '../../../__mocks__/kea_logic'; + +import { nextTick } from '@kbn/test-jest-helpers'; + +import { deleteAnalyticsCollection } from './delete_analytics_collection_api_logic'; + +describe('DeleteAnalyticsCollectionApiLogic', () => { + const { http } = mockHttpValues; + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('DeleteAnalyticsCollectionsApiLogic', () => { + it('calls the analytics collections list api', async () => { + const promise = Promise.resolve(); + const name = 'collection'; + http.delete.mockReturnValue(promise); + const result = deleteAnalyticsCollection({ name }); + await nextTick(); + expect(http.delete).toHaveBeenCalledWith( + `/internal/enterprise_search/analytics/collections/${name}` + ); + await expect(result).resolves.toEqual(undefined); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx new file mode 100644 index 00000000000000..0b2f092899a6fb --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/api/delete_analytics_collection/delete_analytics_collection_api_logic.tsx @@ -0,0 +1,24 @@ +/* + * 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 { createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { HttpLogic } from '../../../shared/http'; + +export type DeleteAnalyticsCollectionApiLogicResponse = void; + +export const deleteAnalyticsCollection = async ({ name }: { name: string }) => { + const { http } = HttpLogic.values; + const route = `/internal/enterprise_search/analytics/collections/${name}`; + await http.delete<DeleteAnalyticsCollectionApiLogicResponse>(route); + + return; +}; + +export const DeleteAnalyticsCollectionAPILogic = createApiLogic( + ['analytics', 'delete_analytics_collection_api_logic'], + deleteAnalyticsCollection +); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.test.ts new file mode 100644 index 00000000000000..ae21c61a8fad23 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.test.ts @@ -0,0 +1,33 @@ +/* + * 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 { mockHttpValues } from '../../../__mocks__/kea_logic'; + +import { nextTick } from '@kbn/test-jest-helpers'; + +import { fetchAnalyticsCollection } from './fetch_analytics_collection_api_logic'; + +describe('FetchAnalyticsCollectionApiLogic', () => { + const { http } = mockHttpValues; + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('FetchAnalyticsCollectionsApiLogic', () => { + it('calls the analytics collections list api', async () => { + const promise = Promise.resolve({ name: 'result' }); + const name = 'collection'; + http.get.mockReturnValue(promise); + const result = fetchAnalyticsCollection({ name }); + await nextTick(); + expect(http.get).toHaveBeenCalledWith( + `/internal/enterprise_search/analytics/collections/${name}` + ); + await expect(result).resolves.toEqual({ name: 'result' }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.tsx new file mode 100644 index 00000000000000..5aafc82c29e0ef --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/api/fetch_analytics_collection/fetch_analytics_collection_api_logic.tsx @@ -0,0 +1,26 @@ +/* + * 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 { AnalyticsCollection } from '../../../../../common/types/analytics'; + +import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { HttpLogic } from '../../../shared/http'; + +export type FetchAnalyticsCollectionApiLogicResponse = AnalyticsCollection; + +export const fetchAnalyticsCollection = async ({ name }: { name: string }) => { + const { http } = HttpLogic.values; + const route = `/internal/enterprise_search/analytics/collections/${name}`; + const response = await http.get<AnalyticsCollection>(route); + + return response; +}; + +export const FetchAnalyticsCollectionAPILogic = createApiLogic( + ['analytics', 'analytics_collection_api_logic'], + fetchAnalyticsCollection +); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.test.ts index b9355574e0806e..7b281208f79e8b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.test.ts @@ -110,7 +110,7 @@ describe('addAnalyticsCollectionLogic', () => { expect(flashSuccessToast).toHaveBeenCalled(); jest.advanceTimersByTime(1000); await nextTick(); - expect(navigateToUrl).toHaveBeenCalledWith('/collections/test'); + expect(navigateToUrl).toHaveBeenCalledWith('/collections/test/events'); jest.useRealTimers(); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts index a1035168d8e87c..3731bb3994e9ef 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/add_analytics_collections/add_analytics_collection_logic.ts @@ -78,6 +78,7 @@ export const AddAnalyticsCollectionLogic = kea< KibanaLogic.values.navigateToUrl( generateEncodedPath(COLLECTION_VIEW_PATH, { name, + section: 'events', }) ); }, diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx new file mode 100644 index 00000000000000..f46454e45eb820 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.test.tsx @@ -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 '../../../__mocks__/shallow_useeffect.mock'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiCodeBlock } from '@elastic/eui'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; + +import { AnalyticsCollectionIntegrate } from './analytics_collection_integrate'; + +describe('AnalyticsCollectionIntegrate', () => { + const analyticsCollections: AnalyticsCollection = { + event_retention_day_length: 180, + id: '1', + name: 'example', + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders', () => { + const wrapper = shallow(<AnalyticsCollectionIntegrate collection={analyticsCollections} />); + expect(wrapper.find(EuiCodeBlock)).toHaveLength(2); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx new file mode 100644 index 00000000000000..ff5cdf9c5fee17 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_integrate.tsx @@ -0,0 +1,121 @@ +/* + * 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 { + EuiCodeBlock, + EuiDescriptionList, + EuiPanel, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; +import { getEnterpriseSearchUrl } from '../../../shared/enterprise_search_url'; + +interface AnalyticsCollectionIntegrateProps { + collection: AnalyticsCollection; +} + +export const AnalyticsCollectionIntegrate: React.FC<AnalyticsCollectionIntegrateProps> = ({ + collection, +}) => { + const analyticsDNSUrl = getEnterpriseSearchUrl(`/analytics/${collection.name}`); + const credentials = [ + { + title: i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.credentials.collectionName', + { + defaultMessage: 'Collection name', + } + ), + description: collection.name, + }, + { + title: i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.credentials.collectionDns', + { + defaultMessage: 'DNS URL', + } + ), + description: analyticsDNSUrl, + }, + ]; + const webclientSrc = getEnterpriseSearchUrl('/analytics.js'); + + return ( + <> + <EuiTitle> + <h4> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.credentials.headingTitle', + { + defaultMessage: 'Credentials', + } + )} + </h4> + </EuiTitle> + <EuiSpacer size="s" /> + <EuiPanel hasShadow={false} color="subdued" paddingSize="xl" grow={false}> + <EuiDescriptionList listItems={credentials} type="column" align="center" /> + </EuiPanel> + + <EuiSpacer size="l" /> + + <EuiTitle> + <h4> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.embed.headingTitle', + { + defaultMessage: 'Start tracking events', + } + )} + </h4> + </EuiTitle> + <EuiSpacer size="s" /> + <EuiText size="s"> + <p> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.embed.description', + { + defaultMessage: + 'Embed the JS snippet below on every page of the website or application you’d like to tracks.', + } + )} + </p> + </EuiText> + <EuiSpacer size="s" /> + <EuiCodeBlock language="html" isCopyable> + {`<script src="${webclientSrc}" data-dsn="${analyticsDNSUrl}" defer></script>`} + </EuiCodeBlock> + + <EuiSpacer size="l" /> + <EuiText size="s"> + <p> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.integrateTab.scriptDescription', + { + defaultMessage: + 'Track individual events, like clicks, by calling the <strong>trackEvent</strong> method.', + } + )} + </p> + </EuiText> + <EuiSpacer size="s" /> + <EuiCodeBlock language="js" isCopyable> + {`window.elasticAnalytics.trackEvent("ResultClick", { + title: "Website Analytics", + url: "www.elasitc.co/analytics/website" +})`} + </EuiCodeBlock> + </> + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.test.tsx new file mode 100644 index 00000000000000..c2d4374c5a4f6d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.test.tsx @@ -0,0 +1,51 @@ +/* + * 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 { setMockActions } from '../../../__mocks__/kea_logic'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiButton, EuiPanel } from '@elastic/eui'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; + +import { AnalyticsCollectionSettings } from './analytics_collection_settings'; + +const mockActions = { + deleteAnalyticsCollection: jest.fn(), + setNameValue: jest.fn(), +}; + +const analyticsCollection: AnalyticsCollection = { + event_retention_day_length: 180, + id: '1', + name: 'example', +}; + +describe('AnalyticsCollectionSettings', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders', () => { + setMockActions(mockActions); + + const wrapper = shallow(<AnalyticsCollectionSettings collection={analyticsCollection} />); + expect(wrapper.find(EuiPanel)).toHaveLength(2); + }); + + it('deletes analytics collection when delete is clicked', () => { + setMockActions(mockActions); + + const wrapper = shallow(<AnalyticsCollectionSettings collection={analyticsCollection} />); + + wrapper.find(EuiButton).simulate('click', { preventDefault: jest.fn() }); + expect(mockActions.deleteAnalyticsCollection).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.tsx new file mode 100644 index 00000000000000..ac3a2fe490e404 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_settings.tsx @@ -0,0 +1,99 @@ +/* + * 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 { useActions, useValues } from 'kea'; + +import { + EuiPanel, + EuiSpacer, + EuiText, + EuiTitle, + EuiButton, + EuiDescriptionList, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; + +import { DeleteAnalyticsCollectionLogic } from './delete_analytics_collection_logic'; + +interface AnalyticsCollectionSettingsProps { + collection: AnalyticsCollection; +} + +export const AnalyticsCollectionSettings: React.FC<AnalyticsCollectionSettingsProps> = ({ + collection, +}) => { + const { deleteAnalyticsCollection } = useActions(DeleteAnalyticsCollectionLogic); + const { isLoading } = useValues(DeleteAnalyticsCollectionLogic); + + return ( + <> + <EuiPanel hasShadow={false} color="subdued" paddingSize="xl" grow={false}> + <EuiDescriptionList + listItems={[ + { + title: i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.settingsTab.credentials.collectionName', + { + defaultMessage: 'Collection name', + } + ), + description: collection.name, + }, + ]} + type="column" + align="center" + /> + </EuiPanel> + <EuiSpacer size="l" /> + <EuiPanel hasShadow={false} color="danger" paddingSize="l"> + <EuiTitle size="s"> + <h4> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.settingsTab.delete.headingTitle', + { + defaultMessage: 'Delete this analytics collection', + } + )} + </h4> + </EuiTitle> + <EuiSpacer size="s" /> + <EuiText size="s"> + <p> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.settingsTab.delete.warning', + { + defaultMessage: 'This action is irreversible', + } + )} + </p> + </EuiText> + <EuiSpacer /> + <EuiButton + fill + type="submit" + color="danger" + isLoading={!isLoading} + disabled={!isLoading} + onClick={() => { + deleteAnalyticsCollection(collection.name); + }} + > + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.settingsTab.delete.buttonTitle', + { + defaultMessage: 'Delete this collection', + } + )} + </EuiButton> + </EuiPanel> + </> + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.test.tsx new file mode 100644 index 00000000000000..6fc82551818ce6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.test.tsx @@ -0,0 +1,68 @@ +/* + * 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 '../../../__mocks__/shallow_useeffect.mock'; + +import { setMockValues, setMockActions } from '../../../__mocks__/kea_logic'; +import { mockUseParams } from '../../../__mocks__/react_router'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; + +import { AnalyticsCollectionIntegrate } from './analytics_collection_integrate'; +import { AnalyticsCollectionSettings } from './analytics_collection_settings'; + +import { AnalyticsCollectionView } from './analytics_collection_view'; + +const mockValues = { + analyticsCollection: { + event_retention_day_length: 180, + id: '1', + name: 'Analytics Collection 1', + } as AnalyticsCollection, +}; + +const mockActions = { + fetchAnalyticsCollection: jest.fn(), +}; + +describe('AnalyticsOverview', () => { + beforeEach(() => { + jest.clearAllMocks(); + + mockUseParams.mockReturnValue({ name: '1', section: 'settings' }); + }); + + describe('empty state', () => { + it('renders when analytics collection is empty on inital query', () => { + setMockValues({ + ...mockValues, + analyticsCollection: null, + }); + setMockActions(mockActions); + const wrapper = shallow(<AnalyticsCollectionView />); + + expect(mockActions.fetchAnalyticsCollection).toHaveBeenCalled(); + + expect(wrapper.find(AnalyticsCollectionSettings)).toHaveLength(0); + expect(wrapper.find(AnalyticsCollectionIntegrate)).toHaveLength(0); + }); + + it('renders with Data', async () => { + setMockValues(mockValues); + setMockActions(mockActions); + + const wrapper = shallow(<AnalyticsCollectionView />); + + expect(wrapper.find(AnalyticsCollectionSettings)).toHaveLength(1); + expect(mockActions.fetchAnalyticsCollection).toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.tsx new file mode 100644 index 00000000000000..4c8e5a36e4e0f3 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_view.tsx @@ -0,0 +1,189 @@ +/* + * 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, { useEffect } from 'react'; +import { useParams } from 'react-router-dom'; + +import { useActions, useValues } from 'kea'; + +import { + EuiEmptyPrompt, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiTitle, + EuiIcon, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { generateEncodedPath } from '../../../shared/encode_path_params'; +import { KibanaLogic } from '../../../shared/kibana'; +import { EuiButtonTo } from '../../../shared/react_router_helpers'; +import { COLLECTION_CREATION_PATH, COLLECTION_VIEW_PATH } from '../../routes'; + +import { EnterpriseSearchAnalyticsPageTemplate } from '../layout/page_template'; + +import { AnalyticsCollectionIntegrate } from './analytics_collection_integrate'; +import { AnalyticsCollectionSettings } from './analytics_collection_settings'; + +import { FetchAnalyticsCollectionLogic } from './fetch_analytics_collection_logic'; + +export const collectionViewBreadcrumbs = [ + i18n.translate('xpack.enterpriseSearch.analytics.collectionsView.breadcrumb', { + defaultMessage: 'View collection', + }), +]; + +export const AnalyticsCollectionView: React.FC = () => { + const { fetchAnalyticsCollection } = useActions(FetchAnalyticsCollectionLogic); + const { analyticsCollection, isLoading } = useValues(FetchAnalyticsCollectionLogic); + const { name, section } = useParams<{ name: string; section: string }>(); + const { navigateToUrl } = useValues(KibanaLogic); + const collectionViewTabs = [ + { + id: 'events', + label: i18n.translate('xpack.enterpriseSearch.analytics.collectionsView.tabs.eventsName', { + defaultMessage: 'Events', + }), + onClick: () => + navigateToUrl( + generateEncodedPath(COLLECTION_VIEW_PATH, { + name: analyticsCollection?.name, + section: 'events', + }) + ), + isSelected: section === 'events', + }, + { + id: 'integrate', + label: i18n.translate('xpack.enterpriseSearch.analytics.collectionsView.tabs.integrateName', { + defaultMessage: 'Integrate', + }), + prepend: <EuiIcon type="editorCodeBlock" size="l" />, + onClick: () => + navigateToUrl( + generateEncodedPath(COLLECTION_VIEW_PATH, { + name: analyticsCollection?.name, + section: 'integrate', + }) + ), + isSelected: section === 'integrate', + }, + { + id: 'settings', + label: i18n.translate('xpack.enterpriseSearch.analytics.collectionsView.tabs.settingsName', { + defaultMessage: 'Settings', + }), + onClick: () => + navigateToUrl( + generateEncodedPath(COLLECTION_VIEW_PATH, { + name: analyticsCollection?.name, + section: 'settings', + }) + ), + isSelected: section === 'settings', + }, + ]; + + useEffect(() => { + fetchAnalyticsCollection(name); + }, []); + + return ( + <EnterpriseSearchAnalyticsPageTemplate + restrictWidth + isLoading={isLoading} + pageChrome={[...collectionViewBreadcrumbs]} + pageViewTelemetry="View Analytics Collection" + pageHeader={{ + description: i18n.translate( + 'xpack.enterpriseSearch.analytics.collectionsView.pageDescription', + { + defaultMessage: + 'Dashboards and tools for visualizing end-user behavior and measuring the performance of your search applications. Track trends over time, identify and investigate anomalies, and make optimizations.', + } + ), + pageTitle: analyticsCollection?.name, + tabs: [...collectionViewTabs], + }} + > + {!analyticsCollection && ( + <EuiFlexGroup> + <EuiFlexItem> + <EuiTitle> + <h2> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.headingTitle', + { + defaultMessage: 'Collections', + } + )} + </h2> + </EuiTitle> + </EuiFlexItem> + <EuiFlexItem grow={false}> + <EuiButtonTo fill iconType="plusInCircle" to={COLLECTION_CREATION_PATH}> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.create.buttonTitle', + { + defaultMessage: 'Create new collection', + } + )} + </EuiButtonTo> + </EuiFlexItem> + </EuiFlexGroup> + )} + + <EuiSpacer size="l" /> + {analyticsCollection ? ( + <> + {section === 'settings' && ( + <AnalyticsCollectionSettings collection={analyticsCollection} /> + )} + {section === 'integrate' && ( + <AnalyticsCollectionIntegrate collection={analyticsCollection} /> + )} + </> + ) : ( + <EuiEmptyPrompt + iconType="search" + title={ + <h2> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.collectionNotFoundState.headingTitle', + { + defaultMessage: 'You may have deleted this analytics collection', + } + )} + </h2> + } + body={ + <p> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.collectionNotFoundState.subHeading', + { + defaultMessage: + 'An analytics collection provides a place to store the analytics events for any given search application you are building. Create a new collection to get started.', + } + )} + </p> + } + actions={[ + <EuiButtonTo fill iconType="plusInCircle" to={COLLECTION_CREATION_PATH}> + {i18n.translate( + 'xpack.enterpriseSearch.analytics.collections.collectionsView.create.buttonTitle', + { + defaultMessage: 'Create new collection', + } + )} + </EuiButtonTo>, + ]} + /> + )} + </EnterpriseSearchAnalyticsPageTemplate> + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts new file mode 100644 index 00000000000000..08ca206671de02 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.test.ts @@ -0,0 +1,84 @@ +/* + * 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 { + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, +} from '../../../__mocks__/kea_logic'; + +import { nextTick } from '@kbn/test-jest-helpers'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; +import { HttpError, Status } from '../../../../../common/types/api'; + +import { DeleteAnalyticsCollectionLogic } from './delete_analytics_collection_logic'; + +describe('deleteAnalyticsCollectionLogic', () => { + const { mount } = new LogicMounter(DeleteAnalyticsCollectionLogic); + const { http } = mockHttpValues; + + beforeEach(() => { + jest.clearAllMocks(); + jest.useRealTimers(); + mount(); + }); + + const DEFAULT_VALUES = { + isLoading: true, + status: Status.IDLE, + }; + + it('has expected default values', () => { + expect(DeleteAnalyticsCollectionLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('listeners', () => { + it('calls clearFlashMessages on new makeRequest', async () => { + const promise = Promise.resolve(undefined); + http.delete.mockReturnValue(promise); + + await nextTick(); + + DeleteAnalyticsCollectionLogic.actions.makeRequest({ name: 'name' } as AnalyticsCollection); + expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); + }); + + it('calls flashAPIErrors on apiError', () => { + DeleteAnalyticsCollectionLogic.actions.apiError({} as HttpError); + expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); + expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); + }); + + it('calls makeRequest on deleteAnalyticsCollections', async () => { + const collectionName = 'name'; + + jest.useFakeTimers(); + DeleteAnalyticsCollectionLogic.actions.makeRequest = jest.fn(); + DeleteAnalyticsCollectionLogic.actions.deleteAnalyticsCollection(collectionName); + jest.advanceTimersByTime(150); + await nextTick(); + expect(DeleteAnalyticsCollectionLogic.actions.makeRequest).toHaveBeenCalledWith({ + name: collectionName, + }); + }); + }); + + describe('selectors', () => { + describe('analyticsCollection', () => { + it('updates when apiSuccess listener triggered', () => { + DeleteAnalyticsCollectionLogic.actions.apiSuccess(); + + expect(DeleteAnalyticsCollectionLogic.values).toEqual({ + ...DEFAULT_VALUES, + isLoading: false, + status: Status.SUCCESS, + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts new file mode 100644 index 00000000000000..0d6bf900f528ae --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/delete_analytics_collection_logic.ts @@ -0,0 +1,73 @@ +/* + * 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 { kea, MakeLogicType } from 'kea'; + +import { i18n } from '@kbn/i18n'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; +import { Status } from '../../../../../common/types/api'; +import { Actions } from '../../../shared/api_logic/create_api_logic'; +import { + flashAPIErrors, + clearFlashMessages, + flashSuccessToast, +} from '../../../shared/flash_messages'; +import { KibanaLogic } from '../../../shared/kibana'; +import { + DeleteAnalyticsCollectionAPILogic, + DeleteAnalyticsCollectionApiLogicResponse, +} from '../../api/delete_analytics_collection/delete_analytics_collection_api_logic'; +import { ROOT_PATH } from '../../routes'; + +export interface DeleteAnalyticsCollectionActions { + apiError: Actions<{}, DeleteAnalyticsCollectionApiLogicResponse>['apiError']; + apiSuccess: Actions<{}, DeleteAnalyticsCollectionApiLogicResponse>['apiSuccess']; + deleteAnalyticsCollection(name: string): { name: string }; + makeRequest: Actions<{}, DeleteAnalyticsCollectionApiLogicResponse>['makeRequest']; +} +export interface DeleteAnalyticsCollectionValues { + analyticsCollection: AnalyticsCollection; + isLoading: boolean; + status: Status; +} + +export const DeleteAnalyticsCollectionLogic = kea< + MakeLogicType<DeleteAnalyticsCollectionValues, DeleteAnalyticsCollectionActions> +>({ + actions: { + deleteAnalyticsCollection: (name) => ({ name }), + }, + connect: { + actions: [DeleteAnalyticsCollectionAPILogic, ['makeRequest', 'apiSuccess', 'apiError']], + values: [DeleteAnalyticsCollectionAPILogic, ['status']], + }, + listeners: ({ actions }) => ({ + apiError: (e) => flashAPIErrors(e), + apiSuccess: async (undefined, breakpoint) => { + flashSuccessToast( + i18n.translate('xpack.enterpriseSearch.analytics.collectionsDelete.action.successMessage', { + defaultMessage: 'The collection has been successfully deleted', + }) + ); + // Wait for propagation of the collection deletion + await breakpoint(1000); + KibanaLogic.values.navigateToUrl(ROOT_PATH); + }, + deleteAnalyticsCollection: ({ name }) => { + actions.makeRequest({ name }); + }, + makeRequest: () => clearFlashMessages(), + }), + path: ['enterprise_search', 'analytics', 'collections', 'delete'], + selectors: ({ selectors }) => ({ + isLoading: [ + () => [selectors.status], + (status) => [Status.LOADING, Status.IDLE].includes(status), + ], + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx new file mode 100644 index 00000000000000..3e56bd816b0a85 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.test.tsx @@ -0,0 +1,73 @@ +/* + * 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 { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_logic'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; +import { HttpError, Status } from '../../../../../common/types/api'; + +import { FetchAnalyticsCollectionLogic } from './fetch_analytics_collection_logic'; + +describe('fetchAnalyticsCollectionLogic', () => { + const { mount } = new LogicMounter(FetchAnalyticsCollectionLogic); + + beforeEach(() => { + jest.clearAllMocks(); + jest.useRealTimers(); + mount(); + }); + + const DEFAULT_VALUES = { + analyticsCollection: null, + data: undefined, + isLoading: true, + status: Status.IDLE, + }; + + it('has expected default values', () => { + expect(FetchAnalyticsCollectionLogic.values).toEqual(DEFAULT_VALUES); + }); + + describe('listeners', () => { + it('calls clearFlashMessages on new makeRequest', () => { + FetchAnalyticsCollectionLogic.actions.makeRequest({} as AnalyticsCollection); + expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1); + }); + + it('calls flashAPIErrors on apiError', () => { + FetchAnalyticsCollectionLogic.actions.apiError({} as HttpError); + expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1); + expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({}); + }); + + it('calls makeRequest on fetchAnalyticsCollections', async () => { + const name = 'name'; + + FetchAnalyticsCollectionLogic.actions.makeRequest = jest.fn(); + FetchAnalyticsCollectionLogic.actions.fetchAnalyticsCollection(name); + expect(FetchAnalyticsCollectionLogic.actions.makeRequest).toHaveBeenCalledWith({ + name, + }); + }); + }); + + describe('selectors', () => { + describe('analyticsCollections', () => { + it('updates when apiSuccess listener triggered', () => { + FetchAnalyticsCollectionLogic.actions.apiSuccess({} as AnalyticsCollection); + + expect(FetchAnalyticsCollectionLogic.values).toEqual({ + ...DEFAULT_VALUES, + analyticsCollection: {}, + data: {}, + isLoading: false, + status: Status.SUCCESS, + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts new file mode 100644 index 00000000000000..819936ff539048 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/fetch_analytics_collection_logic.ts @@ -0,0 +1,57 @@ +/* + * 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 { kea, MakeLogicType } from 'kea'; + +import { AnalyticsCollection } from '../../../../../common/types/analytics'; +import { Status } from '../../../../../common/types/api'; +import { Actions } from '../../../shared/api_logic/create_api_logic'; +import { flashAPIErrors, clearFlashMessages } from '../../../shared/flash_messages'; +import { + FetchAnalyticsCollectionAPILogic, + FetchAnalyticsCollectionApiLogicResponse, +} from '../../api/fetch_analytics_collection/fetch_analytics_collection_api_logic'; + +export interface FetchAnalyticsCollectionActions { + apiError: Actions<{}, FetchAnalyticsCollectionApiLogicResponse>['apiError']; + apiSuccess: Actions<{}, FetchAnalyticsCollectionApiLogicResponse>['apiSuccess']; + fetchAnalyticsCollection(name: string): AnalyticsCollection; + makeRequest: Actions<{}, FetchAnalyticsCollectionApiLogicResponse>['makeRequest']; +} +export interface FetchAnalyticsCollectionValues { + analyticsCollection: AnalyticsCollection; + data: typeof FetchAnalyticsCollectionAPILogic.values.data; + isLoading: boolean; + status: Status; +} + +export const FetchAnalyticsCollectionLogic = kea< + MakeLogicType<FetchAnalyticsCollectionValues, FetchAnalyticsCollectionActions> +>({ + actions: { + fetchAnalyticsCollection: (name) => ({ name }), + }, + connect: { + actions: [FetchAnalyticsCollectionAPILogic, ['makeRequest', 'apiSuccess', 'apiError']], + values: [FetchAnalyticsCollectionAPILogic, ['data', 'status']], + }, + listeners: ({ actions }) => ({ + apiError: (e) => flashAPIErrors(e), + fetchAnalyticsCollection: ({ name }) => { + actions.makeRequest({ name }); + }, + makeRequest: () => clearFlashMessages(), + }), + path: ['enterprise_search', 'analytics', 'collection'], + selectors: ({ selectors }) => ({ + analyticsCollection: [() => [selectors.data], (data) => data || null], + isLoading: [ + () => [selectors.status], + (status) => [Status.LOADING, Status.IDLE].includes(status), + ], + }), +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.test.tsx index bb5e2bfb324c20..8ca63956f6b796 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.test.tsx @@ -39,6 +39,6 @@ describe('AnalyticsCollectionTable', () => { expect(rows).toHaveLength(1); expect(rows[0]).toMatchObject(analyticsCollections[0]); - expect(wrapper.dive().find(EuiLinkTo).first().prop('to')).toBe('/collections/example'); + expect(wrapper.dive().find(EuiLinkTo).first().prop('to')).toBe('/collections/example/events'); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.tsx index 6ce6e677b5a266..6a983fbd5587f9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_overview/analytics_collection_table.tsx @@ -39,6 +39,7 @@ export const AnalyticsCollectionTable: React.FC<AnalyticsCollectionTableProps> = <EuiLinkTo to={generateEncodedPath(COLLECTION_VIEW_PATH, { name, + section: 'events', })} > {name} @@ -57,6 +58,7 @@ export const AnalyticsCollectionTable: React.FC<AnalyticsCollectionTableProps> = navigateToUrl( generateEncodedPath(COLLECTION_VIEW_PATH, { name: collection.name, + section: 'events', }) ), type: 'icon', diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/index.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/index.tsx index 5b41c1e1a653c2..b2f7d20bf261c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/index.tsx @@ -14,9 +14,10 @@ import { VersionMismatchPage } from '../shared/version_mismatch'; import { AddAnalyticsCollection } from './components/add_analytics_collections/add_analytics_collection'; +import { AnalyticsCollectionView } from './components/analytics_collection_view/analytics_collection_view'; import { AnalyticsOverview } from './components/analytics_overview/analytics_overview'; -import { ROOT_PATH, COLLECTION_CREATION_PATH } from './routes'; +import { ROOT_PATH, COLLECTION_CREATION_PATH, COLLECTION_VIEW_PATH } from './routes'; export const Analytics: React.FC<InitialAppData> = (props) => { const { enterpriseSearchVersion, kibanaVersion } = props; @@ -37,6 +38,9 @@ export const Analytics: React.FC<InitialAppData> = (props) => { <Route path={COLLECTION_CREATION_PATH}> <AddAnalyticsCollection /> </Route> + <Route exact path={COLLECTION_VIEW_PATH}> + <AnalyticsCollectionView /> + </Route> </Switch> ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/routes.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/routes.ts index 66803c3e87b10b..14532ecfd50797 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/routes.ts @@ -8,4 +8,4 @@ export const ROOT_PATH = '/'; export const COLLECTIONS_PATH = '/collections'; export const COLLECTION_CREATION_PATH = `${COLLECTIONS_PATH}/new`; -export const COLLECTION_VIEW_PATH = `${COLLECTIONS_PATH}/:name`; +export const COLLECTION_VIEW_PATH = `${COLLECTIONS_PATH}/:name/:section`; diff --git a/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.test.ts b/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.test.ts index dbb9585dbe27c8..a321a0d118cf43 100644 --- a/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.test.ts @@ -40,18 +40,7 @@ describe('delete analytics collection lib function', () => { }); describe('deleting analytics collections', () => { - it('should delete an analytics collection and its events indices', async () => { - const indices = [ - { - name: 'elastic_analytics-events-my-collection-12.12.12', - }, - { - name: 'elastic_analytics-events-my-collection-13.12.12', - }, - ]; - (fetchIndices as jest.Mock).mockImplementationOnce(() => { - return Promise.resolve(indices); - }); + it('should delete an analytics collection', async () => { (fetchAnalyticsCollectionByName as jest.Mock).mockImplementationOnce(() => { return Promise.resolve({ event_retention_day_length: 180, @@ -68,11 +57,6 @@ describe('delete analytics collection lib function', () => { id: 'example-id', index: ANALYTICS_COLLECTIONS_INDEX, }); - - expect(mockClient.asCurrentUser.indices.delete).toHaveBeenCalledWith({ - ignore_unavailable: true, - index: indices.map((index) => index.name), - }); }); it('should throw an exception when analytics collection does not exist', async () => { diff --git a/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.ts b/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.ts index 687296a27c13fd..d07a271bfc01c7 100644 --- a/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.ts +++ b/x-pack/plugins/enterprise_search/server/lib/analytics/delete_analytics_collection.ts @@ -10,20 +10,9 @@ import { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; import { ANALYTICS_COLLECTIONS_INDEX } from '../..'; import { ErrorCode } from '../../../common/types/error_codes'; -import { fetchIndices } from '../indices/fetch_indices'; import { fetchAnalyticsCollectionByName } from './fetch_analytics_collection'; -const deleteAnalyticsCollectionEvents = async (client: IScopedClusterClient, name: string) => { - const indexPattern = `elastic_analytics-events-${name}-*`; - const indices = await fetchIndices(client, indexPattern, true, false); - - await client.asCurrentUser.indices.delete({ - ignore_unavailable: true, - index: indices.map((index) => index.name), - }); -}; - export const deleteAnalyticsCollectionByName = async ( client: IScopedClusterClient, name: string @@ -34,8 +23,6 @@ export const deleteAnalyticsCollectionByName = async ( throw new Error(ErrorCode.ANALYTICS_COLLECTION_NOT_FOUND); } - await deleteAnalyticsCollectionEvents(client, name); - await client.asCurrentUser.delete({ id: analyticsCollection.id, index: ANALYTICS_COLLECTIONS_INDEX, From 2808ecadc9c2f94d3e0d029730296ec94557a7b8 Mon Sep 17 00:00:00 2001 From: Muhammad Ibragimov <53621505+mibragimov@users.noreply.github.com> Date: Tue, 13 Sep 2022 17:31:01 +0500 Subject: [PATCH 103/144] [Console] Add missing autocompletes (#140275) * [Console] Add missing autocompletes * Add script key for moving function aggregation * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: Muhammad Ibragimov <muhammad.ibragimov@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../lib/spec_definitions/js/aggregations.ts | 6 ++- .../server/lib/spec_definitions/js/aliases.ts | 2 + .../overrides/indices.put_index_template.json | 31 ++++++++++++++++ .../json/overrides/slm.put_lifecycle.json | 37 ++++++++++++++++++- 4 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_index_template.json diff --git a/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts b/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts index 9403d6d56e4860..16e7a77366c7dd 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/aggregations.ts @@ -301,6 +301,9 @@ const rules = { format: 'yyyy-MM-dd', time_zone: '00:00', missing: '', + calendar_interval: { + __one_of: ['year', 'quarter', 'week', 'day', 'hour', 'minute', 'second'], + }, }, geo_distance: { __template: { @@ -473,7 +476,7 @@ const rules = { percents: [], }, sum_bucket: simple_pipeline, - moving_avg: { + moving_fn: { __template: { buckets_path: '', }, @@ -489,6 +492,7 @@ const rules = { gamma: 0.5, period: 7, }, + script: '', }, cumulative_sum: { __template: { diff --git a/src/plugins/console/server/lib/spec_definitions/js/aliases.ts b/src/plugins/console/server/lib/spec_definitions/js/aliases.ts index 9eb7554fabeba4..ef4a30c1aa012e 100644 --- a/src/plugins/console/server/lib/spec_definitions/js/aliases.ts +++ b/src/plugins/console/server/lib/spec_definitions/js/aliases.ts @@ -14,6 +14,8 @@ export const aliases = (specService: SpecDefinitionsService) => { routing: '1', search_routing: '1,2', index_routing: '1', + is_write_index: false, + is_hidden: false, }; specService.addGlobalAutocompleteRules('aliases', { '*': aliasRules, diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_index_template.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_index_template.json new file mode 100644 index 00000000000000..95d3eabc97c36e --- /dev/null +++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/indices.put_index_template.json @@ -0,0 +1,31 @@ +{ + "indices.put_index_template": { + "data_autocomplete_rules": { + "composed_of": [], + "index_patterns": [], + "data_stream": { + "__template": { + "allow_custom_routing": false, + "hidden": false, + "index_mode": "" + } + }, + "template": { + "settings": { + "__scope_link": "put_settings" + }, + "aliases": { + "__template": { + "NAME": {} + } + }, + "mappings": { + "__scope_link": "put_mapping" + } + }, + "_meta": {}, + "priority": 0, + "version": 0 + } + } +} diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/slm.put_lifecycle.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/slm.put_lifecycle.json index f14fa5a4ad634e..ae653df104b511 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/overrides/slm.put_lifecycle.json +++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/slm.put_lifecycle.json @@ -4,7 +4,42 @@ "schedule": "", "name": "", "repository": "", - "config": {} + "config": { + "expanded_wildcards": { + "__one_of": [ + "open", + "closed", + "hidden", + "none", + "all" + ] + }, + "ignore_unavailable": false, + "include_global_state": false, + "indices": [ + "" + ], + "feature_states": [ + "" + ], + "partial": false, + "metadata": {} + }, + "retention": { + "expire_after": { + "__one_of": [ + "d", + "h", + "m", + "s", + "ms", + "micros", + "nanos" + ] + }, + "min_count": 0, + "max_count": 0 + } } } } From 8e5ed87f18e1a6c7b43644a9cb024a146b2a6420 Mon Sep 17 00:00:00 2001 From: Anton Dosov <anton.dosov@elastic.co> Date: Tue, 13 Sep 2022 14:37:09 +0200 Subject: [PATCH 104/144] [Mappings Editor] allow time series related properties (#140278) --- .../constants/parameters_definition.tsx | 14 ++++++++++++++ .../mappings_editor/types/document_fields.ts | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx index ae5915a032b8e5..c00885de6b9678 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/constants/parameters_definition.tsx @@ -1078,4 +1078,18 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio }, schema: t.union([t.literal(2), t.literal(3), t.literal(4)]), }, + time_series_metric: { + fieldConfig: { + defaultValue: null, + type: FIELD_TYPES.SELECT, + }, + schema: t.union([t.literal('gauge'), t.literal('counter'), t.null]), + }, + time_series_dimension: { + fieldConfig: { + type: FIELD_TYPES.CHECKBOX, + defaultValue: false, + }, + schema: t.boolean, + }, }; diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts index 408339f5a10a69..6e50cdfe3ba9ad 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/types/document_fields.ts @@ -156,7 +156,9 @@ export type ParameterName = | 'relations' | 'max_shingle_size' | 'value' - | 'meta'; + | 'meta' + | 'time_series_metric' + | 'time_series_dimension'; export interface Parameter { fieldConfig: FieldConfig; From 678edce2d81ae84327fb82291a6f51d9026b7cc7 Mon Sep 17 00:00:00 2001 From: Anton Dosov <anton.dosov@elastic.co> Date: Tue, 13 Sep 2022 14:41:40 +0200 Subject: [PATCH 105/144] Enable TSDB downsampling ILM configuration (#138748) --- .../downsample_interval.test.ts | 130 ++++++++++++++++++ .../policy_serialization.test.ts | 9 ++ .../helpers/actions/downsample_actions.ts | 44 ++++++ .../helpers/actions/index.ts | 1 + .../helpers/actions/phases.ts | 4 + .../common/types/policies.ts | 9 ++ .../phases/cold_phase/cold_phase.tsx | 3 + .../components/phases/hot_phase/hot_phase.tsx | 2 + .../phases/shared_fields/downsample_field.tsx | 82 +++++++++++ .../components/phases/shared_fields/index.ts | 2 + .../searchable_snapshot_field.tsx | 2 +- .../phases/warm_phase/warm_phase.tsx | 3 + .../sections/edit_policy/constants.ts | 39 ++++++ .../sections/edit_policy/form/deserializer.ts | 33 +++++ .../sections/edit_policy/form/schema.ts | 64 ++++++++- .../edit_policy/form/serializer/serializer.ts | 39 ++++++ .../sections/edit_policy/form/validations.ts | 103 +++++++++++++- .../sections/edit_policy/i18n_texts.ts | 15 ++ .../application/sections/edit_policy/types.ts | 15 +- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 22 files changed, 590 insertions(+), 12 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts create mode 100644 x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/downsample_actions.ts create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/downsample_field.tsx diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts new file mode 100644 index 00000000000000..b24a6d1a32cb7d --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/form_validation/downsample_interval.test.ts @@ -0,0 +1,130 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +import { i18nTexts } from '../../../../public/application/sections/edit_policy/i18n_texts'; + +import { PhaseWithDownsample } from '../../../../common/types'; +import { setupEnvironment } from '../../helpers'; +import { setupValidationTestBed, ValidationTestBed } from './validation.helpers'; + +describe('<EditPolicy /> downsample interval validation', () => { + let testBed: ValidationTestBed; + let actions: ValidationTestBed['actions']; + const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); + + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + beforeEach(async () => { + httpRequestsMockHelpers.setDefaultResponses(); + httpRequestsMockHelpers.setLoadPolicies([]); + + await act(async () => { + testBed = await setupValidationTestBed(httpSetup); + }); + + const { component } = testBed; + component.update(); + ({ actions } = testBed); + await actions.setPolicyName('mypolicy'); + }); + + [ + { + name: `doesn't allow empty interval`, + value: '', + error: [i18nTexts.editPolicy.errors.numberRequired], + }, + { + name: `doesn't allow 0 for interval`, + value: '0', + error: [i18nTexts.editPolicy.errors.numberGreatThan0Required], + }, + { + name: `doesn't allow -1 for interval`, + value: '-1', + error: [i18nTexts.editPolicy.errors.numberGreatThan0Required], + }, + { + name: `doesn't allow decimals for timing (with dot)`, + value: '5.5', + error: [i18nTexts.editPolicy.errors.integerRequired], + }, + { + name: `doesn't allow decimals for timing (with comma)`, + value: '5,5', + error: [i18nTexts.editPolicy.errors.integerRequired], + }, + ].forEach((testConfig: { name: string; value: string; error: string[] }) => { + (['hot', 'warm', 'cold'] as PhaseWithDownsample[]).forEach((phase: PhaseWithDownsample) => { + const { name, value, error } = testConfig; + test(`${phase}: ${name}`, async () => { + if (phase !== 'hot') { + await actions.togglePhase(phase); + } + + await actions[phase].downsample.toggle(); + + // 1. We first set as dummy value to have a starting min_age value + await actions[phase].downsample.setDownsampleInterval('111'); + // 2. At this point we are sure there will be a change of value and that any validation + // will be displayed under the field. + await actions[phase].downsample.setDownsampleInterval(value); + + actions.errors.waitForValidation(); + + actions.errors.expectMessages(error); + }); + }); + }); + + test('should validate an interval is greater or multiple than previous phase interval', async () => { + await actions.togglePhase('warm'); + await actions.togglePhase('cold'); + + await actions.hot.downsample.toggle(); + await actions.hot.downsample.setDownsampleInterval('60', 'm'); + + await actions.warm.downsample.toggle(); + await actions.warm.downsample.setDownsampleInterval('1', 'h'); + + actions.errors.waitForValidation(); + actions.errors.expectMessages( + ['Must be greater than and a multiple of the hot phase value (60m)'], + 'warm' + ); + + await actions.cold.downsample.toggle(); + await actions.cold.downsample.setDownsampleInterval('90', 'm'); + actions.errors.waitForValidation(); + actions.errors.expectMessages( + ['Must be greater than and a multiple of the warm phase value (1h)'], + 'cold' + ); + + // disable warm phase; + await actions.togglePhase('warm'); + // TODO: there is a bug that disabling a phase doesn't trigger downsample validation in other phases, + // users can work around it by changing the value + await actions.cold.downsample.setDownsampleInterval('120', 'm'); + actions.errors.waitForValidation(); + actions.errors.expectMessages([], 'cold'); + + await actions.cold.downsample.setDownsampleInterval('90', 'm'); + actions.errors.waitForValidation(); + actions.errors.expectMessages( + ['Must be greater than and a multiple of the hot phase value (60m)'], + 'cold' + ); + }); +}); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts index 14f1403ad536d7..321a7efbfc5e3c 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts @@ -201,6 +201,8 @@ describe('<EditPolicy /> serialization', () => { await actions.hot.setShrinkCount('2'); await actions.hot.toggleReadonly(); await actions.hot.setIndexPriority('123'); + await actions.hot.downsample.toggle(); + await actions.hot.downsample.setDownsampleInterval('2', 'h'); await actions.savePolicy(); @@ -231,6 +233,7 @@ describe('<EditPolicy /> serialization', () => { priority: 123, }, readonly: {}, + downsample: { fixed_interval: '2h' }, }, }, }, @@ -323,6 +326,8 @@ describe('<EditPolicy /> serialization', () => { await actions.warm.setBestCompression(true); await actions.warm.toggleReadonly(); await actions.warm.setIndexPriority('123'); + await actions.warm.downsample.toggle(); + await actions.warm.downsample.setDownsampleInterval('20', 'm'); await actions.savePolicy(); expect(httpSetup.post).toHaveBeenLastCalledWith( @@ -360,6 +365,7 @@ describe('<EditPolicy /> serialization', () => { number_of_replicas: 123, }, readonly: {}, + downsample: { fixed_interval: '20m' }, }, }, }, @@ -463,6 +469,8 @@ describe('<EditPolicy /> serialization', () => { await actions.cold.setReplicas('123'); await actions.cold.toggleReadonly(); await actions.cold.setIndexPriority('123'); + await actions.cold.downsample.toggle(); + await actions.cold.downsample.setDownsampleInterval('5'); await actions.savePolicy(); @@ -494,6 +502,7 @@ describe('<EditPolicy /> serialization', () => { number_of_replicas: 123, }, readonly: {}, + downsample: { fixed_interval: '5d' }, }, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/downsample_actions.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/downsample_actions.ts new file mode 100644 index 00000000000000..315ed3d58520a6 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/downsample_actions.ts @@ -0,0 +1,44 @@ +/* + * 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 { TestBed } from '@kbn/test-jest-helpers'; +import { act } from 'react-dom/test-utils'; +import { Phase } from '../../../../common/types'; +import { createFormToggleAction } from '..'; + +const createSetDownsampleIntervalAction = + (testBed: TestBed, phase: Phase) => async (value: string, units?: string) => { + const { find, component } = testBed; + + await act(async () => { + find(`${phase}-downsampleFixedInterval`).simulate('change', { target: { value } }); + }); + component.update(); + + if (units) { + act(() => { + find(`${phase}-downsampleFixedIntervalUnits.show-filters-button`).simulate('click'); + }); + component.update(); + + act(() => { + find(`${phase}-downsampleFixedIntervalUnits.filter-option-${units}`).simulate('click'); + }); + component.update(); + } + }; + +export const createDownsampleActions = (testBed: TestBed, phase: Phase) => { + const { exists } = testBed; + return { + downsample: { + exists: () => exists(`${phase}-downsampleSwitch`), + toggle: createFormToggleAction(testBed, `${phase}-downsampleSwitch`), + setDownsampleInterval: createSetDownsampleIntervalAction(testBed, phase), + }, + }; +}; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts index f2579031dbad98..fefbd0363d4499 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts @@ -21,6 +21,7 @@ export { createForceMergeActions } from './forcemerge_actions'; export { createReadonlyActions } from './readonly_actions'; export { createIndexPriorityActions } from './index_priority_actions'; export { createShrinkActions } from './shrink_actions'; +export { createDownsampleActions } from './downsample_actions'; export { createHotPhaseActions, createWarmPhaseActions, diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts index d317b09d4d3056..ffe3aad05b0ebd 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts @@ -16,6 +16,7 @@ import { createNodeAllocationActions, createReplicasAction, createSnapshotPolicyActions, + createDownsampleActions, } from '.'; export const createHotPhaseActions = (testBed: TestBed) => { @@ -26,6 +27,7 @@ export const createHotPhaseActions = (testBed: TestBed) => { ...createReadonlyActions(testBed, 'hot'), ...createIndexPriorityActions(testBed, 'hot'), ...createSearchableSnapshotActions(testBed, 'hot'), + ...createDownsampleActions(testBed, 'hot'), }, }; }; @@ -39,6 +41,7 @@ export const createWarmPhaseActions = (testBed: TestBed) => { ...createIndexPriorityActions(testBed, 'warm'), ...createNodeAllocationActions(testBed, 'warm'), ...createReplicasAction(testBed, 'warm'), + ...createDownsampleActions(testBed, 'warm'), }, }; }; @@ -51,6 +54,7 @@ export const createColdPhaseActions = (testBed: TestBed) => { ...createIndexPriorityActions(testBed, 'cold'), ...createNodeAllocationActions(testBed, 'cold'), ...createSearchableSnapshotActions(testBed, 'cold'), + ...createDownsampleActions(testBed, 'cold'), }, }; }; diff --git a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts index 6c5a9b7c36c508..fcc9e89da47963 100644 --- a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts +++ b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts @@ -15,6 +15,8 @@ export type PhaseWithTiming = keyof Omit<Phases, 'hot'>; export type PhaseExceptDelete = keyof Omit<Phases, 'delete'>; +export type PhaseWithDownsample = 'hot' | 'warm' | 'cold'; + export interface SerializedPolicy { name: string; phases: Phases; @@ -93,6 +95,7 @@ export interface SerializedHotPhase extends SerializedPhase { forcemerge?: ForcemergeAction; readonly?: {}; shrink?: ShrinkAction; + downsample?: DownsampleAction; set_priority?: { priority: number | null; @@ -110,6 +113,7 @@ export interface SerializedWarmPhase extends SerializedPhase { shrink?: ShrinkAction; forcemerge?: ForcemergeAction; readonly?: {}; + downsample?: DownsampleAction; set_priority?: { priority: number | null; }; @@ -121,6 +125,7 @@ export interface SerializedColdPhase extends SerializedPhase { actions: { freeze?: {}; readonly?: {}; + downsample?: DownsampleAction; allocate?: AllocateAction; set_priority?: { priority: number | null; @@ -178,6 +183,10 @@ export interface ForcemergeAction { index_codec?: 'best_compression'; } +export interface DownsampleAction { + fixed_interval: string; +} + export interface LegacyPolicy { name: string; phases: { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx index 58f85441740441..e3214eab3ec47d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx @@ -15,6 +15,7 @@ import { IndexPriorityField, ReplicasField, ReadonlyField, + DownsampleField, } from '../shared_fields'; import { Phase } from '../phase'; @@ -38,6 +39,8 @@ export const ColdPhase: FunctionComponent = () => { {/* Readonly section */} {!isUsingSearchableSnapshotInHotPhase && <ReadonlyField phase="cold" />} + {!isUsingSearchableSnapshotInHotPhase && <DownsampleField phase="cold" />} + {/* Data tier allocation section */} <DataTierAllocationField description={i18nTexts.dataTierAllocation.description} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx index c5d1cc921dda63..4d645a9d2066b6 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx @@ -29,6 +29,7 @@ import { SearchableSnapshotField, ReadonlyField, ShrinkField, + DownsampleField, } from '../shared_fields'; import { Phase } from '../phase'; @@ -176,6 +177,7 @@ export const HotPhase: FunctionComponent = () => { <ShrinkField phase={'hot'} /> {license.canUseSearchableSnapshot() && <SearchableSnapshotField phase="hot" />} <ReadonlyField phase={'hot'} /> + <DownsampleField phase="hot" /> </> )} <IndexPriorityField phase={'hot'} /> diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/downsample_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/downsample_field.tsx new file mode 100644 index 00000000000000..e25068be8b13a5 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/downsample_field.tsx @@ -0,0 +1,82 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n-react'; +import { EuiTextColor } from '@elastic/eui'; +import { UnitField } from './unit_field'; +import { fixedIntervalUnits } from '../../../constants'; +import { UseField } from '../../../form'; +import { NumericField } from '../../../../../../shared_imports'; +import { ToggleFieldWithDescribedFormRow } from '../../described_form_row'; +// import { LearnMoreLink } from '../../learn_more_link'; +import { i18nTexts } from '../../../i18n_texts'; +import { PhaseWithDownsample } from '../../../../../../../common/types'; + +interface Props { + phase: PhaseWithDownsample; +} + +export const DownsampleField: React.FunctionComponent<Props> = ({ phase }) => { + // const { docLinks } = useKibana().services; + + const downsampleEnabledPath = `_meta.${phase}.downsample.enabled`; + const downsampleIntervalSizePath = `_meta.${phase}.downsample.fixedIntervalSize`; + const downsampleIntervalUnitsPath = `_meta.${phase}.downsample.fixedIntervalUnits`; + + return ( + <ToggleFieldWithDescribedFormRow + title={ + <h3> + <FormattedMessage + id="xpack.indexLifecycleMgmt.editPolicy.downsampleTitle" + defaultMessage="Downsample" + /> + </h3> + } + description={ + <EuiTextColor color="subdued"> + <FormattedMessage + id="xpack.indexLifecycleMgmt.editPolicy.downsampleDescription" + defaultMessage="Roll up documents within a fixed interval to a single summary document. Reduces the index footprint by storing time series data at reduced granularity." + />{' '} + {/* TODO: add when available*/} + {/* <LearnMoreLink docPath={docLinks.links.elasticsearch.ilmDownsample} /> */} + </EuiTextColor> + } + fullWidth + titleSize="xs" + switchProps={{ + 'data-test-subj': `${phase}-downsampleSwitch`, + path: downsampleEnabledPath, + }} + > + <UseField + path={downsampleIntervalSizePath} + key={downsampleIntervalSizePath} + component={NumericField} + componentProps={{ + fullWidth: false, + euiFieldProps: { + 'data-test-subj': `${phase}-downsampleFixedInterval`, + min: 1, + append: ( + <UnitField + path={downsampleIntervalUnitsPath} + options={fixedIntervalUnits} + euiFieldProps={{ + 'data-test-subj': `${phase}-downsampleFixedIntervalUnits`, + 'aria-label': i18nTexts.editPolicy.downsampleIntervalFieldUnitsLabel, + }} + /> + ), + }, + }} + /> + </ToggleFieldWithDescribedFormRow> + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts index 220f0bd8e941a8..34f4d09877e3ab 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts @@ -22,3 +22,5 @@ export { ReadonlyField } from './readonly_field'; export { ReplicasField } from './replicas_field'; export { IndexPriorityField } from './index_priority_field'; + +export { DownsampleField } from './downsample_field'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx index fbf5dc5c5af4b3..f36067923e1b7e 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx @@ -265,7 +265,7 @@ export const SearchableSnapshotField: FunctionComponent<Props> = ({ 'xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody', { defaultMessage: - 'Force merge, shrink and read only actions are not allowed when converting data to a fully-mounted index in this phase.', + 'Force merge, shrink, downsample and read only actions are not allowed when converting data to a fully-mounted index in this phase.', } )} data-test-subj="searchableSnapshotFieldsDisabledCallout" diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx index 29445ac8e4715e..fba9556b5f4eaa 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx @@ -17,6 +17,7 @@ import { ShrinkField, ReadonlyField, ReplicasField, + DownsampleField, } from '../shared_fields'; import { Phase } from '../phase'; @@ -42,6 +43,8 @@ export const WarmPhase: FunctionComponent = () => { {!isUsingSearchableSnapshotInHotPhase && <ReadonlyField phase="warm" />} + {!isUsingSearchableSnapshotInHotPhase && <DownsampleField phase="warm" />} + {/* Data tier allocation section */} <DataTierAllocationField description={i18nTexts.dataTierAllocation.description} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/constants.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/constants.ts index 9b708e0d464d22..f36c7cc69977b8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/constants.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/constants.ts @@ -118,3 +118,42 @@ export const timeUnits = [ }), }, ]; + +/* + * Labels for fixed intervals + */ +export const fixedIntervalUnits = [ + { + value: 'd', + text: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.fixedIntervalUnits.daysLabel', { + defaultMessage: 'days', + }), + }, + { + value: 'h', + text: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.fixedIntervalUnits.hoursLabel', { + defaultMessage: 'hours', + }), + }, + { + value: 'm', + text: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.fixedIntervalUnits.minutesLabel', { + defaultMessage: 'minutes', + }), + }, + { + value: 's', + text: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.fixedIntervalUnits.secondsLabel', { + defaultMessage: 'seconds', + }), + }, + { + value: 'ms', + text: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.fixedIntervalUnits.millisecondsLabel', + { + defaultMessage: 'milliseconds', + } + ), + }, +]; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts index 73c15c864b2af7..6a0dae8d3deaf7 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts @@ -40,6 +40,9 @@ export const createDeserializer = bestCompression: hot?.actions?.forcemerge?.index_codec === 'best_compression', readonlyEnabled: Boolean(hot?.actions?.readonly), shrink: { isUsingShardSize: Boolean(hot?.actions.shrink?.max_primary_shard_size) }, + downsample: { + enabled: Boolean(hot?.actions?.downsample), + }, }, warm: { enabled: Boolean(warm), @@ -49,12 +52,18 @@ export const createDeserializer = readonlyEnabled: Boolean(warm?.actions?.readonly), minAgeToMilliSeconds: -1, shrink: { isUsingShardSize: Boolean(warm?.actions.shrink?.max_primary_shard_size) }, + downsample: { + enabled: Boolean(warm?.actions?.downsample), + }, }, cold: { enabled: Boolean(cold), dataTierAllocationType: determineDataTierAllocationType(cold?.actions), readonlyEnabled: Boolean(cold?.actions?.readonly), minAgeToMilliSeconds: -1, + downsample: { + enabled: Boolean(cold?.actions?.downsample), + }, }, frozen: { enabled: Boolean(frozen), @@ -105,6 +114,14 @@ export const createDeserializer = draft._meta.hot.shrink.maxPrimaryShardSizeUnits = primaryShardSize.units; } + if (draft.phases.hot?.actions.downsample?.fixed_interval) { + const downsampleInterval = splitSizeAndUnits( + draft.phases.hot.actions.downsample.fixed_interval + ); + draft._meta.hot.downsample.fixedIntervalUnits = downsampleInterval.units; + draft._meta.hot.downsample.fixedIntervalSize = downsampleInterval.size; + } + if (draft.phases.warm) { if (draft.phases.warm.actions?.allocate?.require) { Object.entries(draft.phases.warm.actions.allocate.require).forEach((entry) => { @@ -125,6 +142,14 @@ export const createDeserializer = draft.phases.warm.actions.shrink.max_primary_shard_size = primaryShardSize.size; draft._meta.warm.shrink.maxPrimaryShardSizeUnits = primaryShardSize.units; } + + if (draft.phases.warm?.actions.downsample?.fixed_interval) { + const downsampleInterval = splitSizeAndUnits( + draft.phases.warm.actions.downsample.fixed_interval + ); + draft._meta.warm.downsample.fixedIntervalUnits = downsampleInterval.units; + draft._meta.warm.downsample.fixedIntervalSize = downsampleInterval.size; + } } if (draft.phases.cold) { @@ -139,6 +164,14 @@ export const createDeserializer = draft.phases.cold.min_age = minAge.size; draft._meta.cold.minAgeUnit = minAge.units; } + + if (draft.phases.cold?.actions.downsample?.fixed_interval) { + const downsampleInterval = splitSizeAndUnits( + draft.phases.cold.actions.downsample.fixed_interval + ); + draft._meta.cold.downsample.fixedIntervalUnits = downsampleInterval.units; + draft._meta.cold.downsample.fixedIntervalSize = downsampleInterval.size; + } } if (draft.phases.frozen) { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts index 0e9f4bd953c2ab..2299cd2fed3444 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts @@ -7,17 +7,22 @@ import { i18n } from '@kbn/i18n'; -import { PhaseExceptDelete, PhaseWithTiming } from '../../../../../common/types'; -import { FormSchema, fieldValidators } from '../../../../shared_imports'; +import { + PhaseExceptDelete, + PhaseWithDownsample, + PhaseWithTiming, +} from '../../../../../common/types'; +import { fieldValidators, FormSchema } from '../../../../shared_imports'; import { defaultIndexPriority } from '../../../constants'; -import { ROLLOVER_FORM_PATHS, CLOUD_DEFAULT_REPO } from '../constants'; +import { CLOUD_DEFAULT_REPO, ROLLOVER_FORM_PATHS } from '../constants'; import { i18nTexts } from '../i18n_texts'; import { ifExistsNumberGreaterThanZero, ifExistsNumberNonNegative, - rolloverThresholdsValidator, integerValidator, minAgeGreaterThanPreviousPhase, + rolloverThresholdsValidator, + downsampleIntervalMultipleOfPreviousOne, } from './validations'; const rolloverFormPaths = Object.values(ROLLOVER_FORM_PATHS); @@ -156,6 +161,54 @@ const getMinAgeField = (phase: PhaseWithTiming, defaultValue?: string) => ({ ], }); +const getDownsampleFieldsToValidateOnChange = ( + p: PhaseWithDownsample, + includeCurrentPhase = true +) => { + const allPhases: PhaseWithDownsample[] = ['hot', 'warm', 'cold']; + const getIntervalSizePath = (currentPhase: PhaseWithDownsample) => + `_meta.${currentPhase}.downsample.fixedIntervalSize`; + const omitPreviousPhases = (currentPhase: PhaseWithDownsample) => + allPhases.slice(allPhases.indexOf(currentPhase) + (includeCurrentPhase ? 0 : 1)); + // when a phase is validated, need to also validate all downsample intervals in the next phases + return omitPreviousPhases(p).map(getIntervalSizePath); +}; +const getDownsampleSchema = (phase: PhaseWithDownsample): FormSchema['downsample'] => { + return { + enabled: { + defaultValue: false, + label: i18nTexts.editPolicy.downsampleEnabledFieldLabel, + fieldsToValidateOnChange: getDownsampleFieldsToValidateOnChange( + phase, + /* don't trigger validation on the current validation to prevent showing error state on pristine input */ + false + ), + }, + fixedIntervalSize: { + label: i18nTexts.editPolicy.downsampleIntervalFieldLabel, + fieldsToValidateOnChange: getDownsampleFieldsToValidateOnChange(phase), + validations: [ + { + validator: emptyField(i18nTexts.editPolicy.errors.numberRequired), + }, + { + validator: ifExistsNumberGreaterThanZero, + }, + { + validator: integerValidator, + }, + { + validator: downsampleIntervalMultipleOfPreviousOne(phase), + }, + ], + }, + fixedIntervalUnits: { + defaultValue: 'd', + fieldsToValidateOnChange: getDownsampleFieldsToValidateOnChange(phase), + }, + }; +}; + export const getSchema = (isCloudEnabled: boolean): FormSchema => ({ _meta: { hot: { @@ -197,6 +250,7 @@ export const getSchema = (isCloudEnabled: boolean): FormSchema => ({ defaultValue: 'gb', }, }, + downsample: getDownsampleSchema('hot'), }, warm: { enabled: { @@ -239,6 +293,7 @@ export const getSchema = (isCloudEnabled: boolean): FormSchema => ({ defaultValue: 'gb', }, }, + downsample: getDownsampleSchema('warm'), }, cold: { enabled: { @@ -269,6 +324,7 @@ export const getSchema = (isCloudEnabled: boolean): FormSchema => ({ allocationNodeAttribute: { label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel, }, + downsample: getDownsampleSchema('cold'), }, frozen: { enabled: { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts index 75fb48a5becd3c..c0ae46bf18c4fd 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts @@ -124,6 +124,19 @@ export const createSerializer = } else { delete hotPhaseActions.shrink!.max_primary_shard_size; } + + /** + * HOT PHASE DOWNSAMPLE + */ + if (_meta.hot?.downsample?.enabled) { + hotPhaseActions.downsample = { + ...hotPhaseActions.downsample, + fixed_interval: `${_meta.hot.downsample.fixedIntervalSize!}${_meta.hot.downsample + .fixedIntervalUnits!}`, + }; + } else { + delete hotPhaseActions.downsample; + } } else { delete hotPhaseActions.rollover; delete hotPhaseActions.forcemerge; @@ -214,6 +227,19 @@ export const createSerializer = } else { delete warmPhase.actions.shrink!.max_primary_shard_size; } + + /** + * WARM PHASE DOWNSAMPLE + */ + if (_meta.warm?.downsample?.enabled) { + warmPhase.actions.downsample = { + ...warmPhase.actions.downsample, + fixed_interval: `${_meta.warm.downsample.fixedIntervalSize!}${_meta.warm.downsample + .fixedIntervalUnits!}`, + }; + } else { + delete warmPhase.actions.downsample; + } } else { delete draft.phases.warm; } @@ -278,6 +304,19 @@ export const createSerializer = } else { delete coldPhase.actions.searchable_snapshot; } + + /** + * COLD PHASE DOWNSAMPLE + */ + if (_meta.cold?.downsample?.enabled) { + coldPhase.actions.downsample = { + ...coldPhase.actions.downsample, + fixed_interval: `${_meta.cold.downsample.fixedIntervalSize!}${_meta.cold.downsample + .fixedIntervalUnits!}`, + }; + } else { + delete coldPhase.actions.downsample; + } } else { delete draft.phases.cold; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts index 04f59707ea634d..5035071a1f2a14 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/validations.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; +import moment from 'moment'; import { fieldValidators, ValidationFunc, @@ -16,7 +17,7 @@ import { import { ROLLOVER_FORM_PATHS } from '../constants'; import { i18nTexts } from '../i18n_texts'; -import { PhaseWithTiming, PolicyFromES } from '../../../../../common/types'; +import { PhaseWithDownsample, PhaseWithTiming, PolicyFromES } from '../../../../../common/types'; import { FormInternal } from '../types'; const { numberGreaterThanField, containsCharsField, emptyField, startsWithField } = fieldValidators; @@ -272,3 +273,103 @@ export const minAgeGreaterThanPreviousPhase = } } }; + +export const downsampleIntervalMultipleOfPreviousOne = + (phase: PhaseWithDownsample) => + ({ formData }: { formData: Record<string, any> }) => { + if (phase === 'hot') return; + + const getValueFor = (_phase: PhaseWithDownsample) => { + const intervalSize = formData[`_meta.${_phase}.downsample.fixedIntervalSize`]; + const intervalUnits = formData[`_meta.${_phase}.downsample.fixedIntervalUnits`]; + + if (!intervalSize || !intervalUnits) { + return null; + } + + const milliseconds = moment.duration(intervalSize, intervalUnits).asMilliseconds(); + const esFormat = intervalSize + intervalUnits; + + return { + milliseconds, + esFormat, + }; + }; + + const intervalValues = { + hot: getValueFor('hot'), + warm: getValueFor('warm'), + cold: getValueFor('cold'), + }; + + const checkIfGreaterAndMultiple = (nextInterval: number, previousInterval: number): boolean => + nextInterval > previousInterval && nextInterval % previousInterval === 0; + + if (phase === 'warm' && intervalValues.warm) { + if (intervalValues.hot) { + if ( + !checkIfGreaterAndMultiple( + intervalValues.warm.milliseconds, + intervalValues.hot.milliseconds + ) + ) { + return { + message: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.downsamplePreviousIntervalWarmPhaseError', + { + defaultMessage: + 'Must be greater than and a multiple of the hot phase value ({value})', + values: { + value: intervalValues.hot.esFormat, + }, + } + ), + }; + } + } + } + + if (phase === 'cold' && intervalValues.cold) { + if (intervalValues.warm) { + if ( + !checkIfGreaterAndMultiple( + intervalValues.cold.milliseconds, + intervalValues.warm.milliseconds + ) + ) { + return { + message: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.downsamplePreviousIntervalColdPhaseWarmError', + { + defaultMessage: + 'Must be greater than and a multiple of the warm phase value ({value})', + values: { + value: intervalValues.warm.esFormat, + }, + } + ), + }; + } + } else if (intervalValues.hot) { + if ( + !checkIfGreaterAndMultiple( + intervalValues.cold.milliseconds, + intervalValues.hot.milliseconds + ) + ) { + return { + message: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.downsamplePreviousIntervalColdPhaseHotError', + { + defaultMessage: + 'Must be greater than and a multiple of the hot phase value ({value})', + values: { + value: intervalValues.hot.esFormat, + }, + } + ), + }; + } + } + } + }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts index f54a782ea13345..b4d9c5282d6782 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/i18n_texts.ts @@ -54,6 +54,21 @@ export const i18nTexts = { readonlyEnabledFieldLabel: i18n.translate('xpack.indexLifecycleMgmt.readonlyFieldLabel', { defaultMessage: 'Make index read only', }), + downsampleEnabledFieldLabel: i18n.translate('xpack.indexLifecycleMgmt.downsampleFieldLabel', { + defaultMessage: 'Enable downsampling', + }), + downsampleIntervalFieldLabel: i18n.translate( + 'xpack.indexLifecycleMgmt.downsampleIntervalFieldLabel', + { + defaultMessage: 'Downsampling interval', + } + ), + downsampleIntervalFieldUnitsLabel: i18n.translate( + 'xpack.indexLifecycleMgmt.downsampleIntervalFieldUnitsLabel', + { + defaultMessage: 'Downsampling interval units', + } + ), maxNumSegmentsFieldLabel: i18n.translate( 'xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel', { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts index 8e83f123a8fa22..5dd5477cae2c25 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts @@ -29,7 +29,15 @@ interface ShrinkFields { }; } -interface HotPhaseMetaFields extends ForcemergeFields, ShrinkFields { +export interface DownsampleFields { + downsample: { + enabled: boolean; + fixedIntervalSize?: string; + fixedIntervalUnits?: string; + }; +} + +interface HotPhaseMetaFields extends ForcemergeFields, ShrinkFields, DownsampleFields { /** * By default rollover is enabled with set values for max age, max size and max docs. In this policy form * opting in to default rollover overrides custom rollover values. @@ -58,13 +66,14 @@ interface WarmPhaseMetaFields extends DataAllocationMetaFields, MinAgeField, ForcemergeFields, - ShrinkFields { + ShrinkFields, + DownsampleFields { enabled: boolean; warmPhaseOnRollover: boolean; readonlyEnabled: boolean; } -interface ColdPhaseMetaFields extends DataAllocationMetaFields, MinAgeField { +interface ColdPhaseMetaFields extends DataAllocationMetaFields, MinAgeField, DownsampleFields { enabled: boolean; readonlyEnabled: boolean; } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 01bbf59adb16fc..c10ded1c3e623d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -15037,7 +15037,6 @@ "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.repositoryHelpText": "Chaque phase utilise le même référentiel de snapshot.", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.storageHelpText": "Type de snapshot installé pour le snapshot qu’il est possible de rechercher. Il s'agit d'une option avancée. Ne la modifiez que si vous savez ce que vous faites.", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.storageLabel": "Stockage", - "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody": "Les actions Forcer la fusion, Réduire et Lecture seule ne sont pas autorisées lors de la conversion des données en index entièrement installé dans cette phase.", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotLicenseCalloutBody": "Licence Enterprise obligatoire pour créer un snapshot qu’il est possible de rechercher.", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotLicenseCalloutTitle": "Licence Enterprise requise", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotRepoFieldLabel": "Référentiel de snapshot", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f6dbbfc7358904..a6a6a929da9dd5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -15025,7 +15025,6 @@ "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.repositoryHelpText": "各フェーズは同じスナップショットリポジトリを使用します。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.storageHelpText": "検索可能なスナップショットにマウントされたスナップショットのタイプ。これは高度なオプションです。作業内容を理解している場合にのみ変更してください。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.storageLabel": "ストレージ", - "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody": "このフェーズでデータを完全にマウントされたインデックスに変換するときには、強制マージ、縮小、読み取り専用アクションは許可されません。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotLicenseCalloutBody": "検索可能なスナップショットを作成するには、エンタープライズライセンスが必要です。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotLicenseCalloutTitle": "エンタープライズライセンスが必要です", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotRepoFieldLabel": "スナップショットリポジトリ", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 60c556135b465b..bd0b538fd94dde 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -15042,7 +15042,6 @@ "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.repositoryHelpText": "每个阶段使用相同的快照存储库。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.storageHelpText": "为可搜索快照安装的快照类型。这是高级选项。只有了解此功能时才能更改。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshot.storageLabel": "存储", - "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody": "在此阶段将数据转换为完全安装的索引时,不允许强制合并、缩小和只读操作。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotLicenseCalloutBody": "要创建可搜索快照,需要企业许可证。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotLicenseCalloutTitle": "需要企业许可证", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotRepoFieldLabel": "快照存储库", From b95485e28ddbf44553b385d2240094f334a8800e Mon Sep 17 00:00:00 2001 From: Shahzad <shahzad.muhammad@elastic.co> Date: Tue, 13 Sep 2022 14:55:50 +0200 Subject: [PATCH 106/144] [Fleet] Improve fleet package policy delete API (#140541) --- .../plugins/fleet/server/errors/handlers.ts | 3 +- .../fleet/server/services/package_policy.ts | 86 +++++++++++++------ 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/fleet/server/errors/handlers.ts b/x-pack/plugins/fleet/server/errors/handlers.ts index da6d245f456a6a..173d295c079c29 100644 --- a/x-pack/plugins/fleet/server/errors/handlers.ts +++ b/x-pack/plugins/fleet/server/errors/handlers.ts @@ -29,6 +29,7 @@ import { RegistryError, RegistryResponseError, PackageFailedVerificationError, + PackagePolicyNotFoundError, } from '.'; type IngestErrorHandler = ( @@ -52,7 +53,7 @@ const getHTTPResponseCode = (error: IngestManagerError): number => { // Connection errors (ie. RegistryConnectionError) / fallback (RegistryError) from EPR return 502; // Bad Gateway } - if (error instanceof PackageNotFoundError) { + if (error instanceof PackageNotFoundError || error instanceof PackagePolicyNotFoundError) { return 404; // Not Found } if (error instanceof AgentPolicyNameExistsError) { diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 2d02e0e710f772..6cd6f373c1104c 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -9,7 +9,6 @@ import { omit, partition, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; import semverLt from 'semver/functions/lt'; import { getFlattenedObject } from '@kbn/std'; -import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import type { KibanaRequest, ElasticsearchClient, @@ -24,6 +23,8 @@ import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import type { AuthenticatedUser } from '@kbn/security-plugin/server'; +import pMap from 'p-map'; + import { packageToPackagePolicy, packageToPackagePolicyInputs, @@ -552,42 +553,54 @@ class PackagePolicyService implements PackagePolicyServiceInterface { ): Promise<DeletePackagePoliciesResponse> { const result: DeletePackagePoliciesResponse = []; - for (const id of ids) { - try { - const packagePolicy = await this.get(soClient, id); - if (!packagePolicy) { - throw new Error('Package policy not found'); - } + const packagePolicies = await this.getByIDs(soClient, ids, { ignoreMissing: true }); + if (!packagePolicies) { + return []; + } - if (packagePolicy.is_managed && !options?.force) { - throw new PackagePolicyRestrictionRelatedError(`Cannot delete package policy ${id}`); - } + const uniqueAgentPolicyIds = [ + ...new Set(packagePolicies.map((packagePolicy) => packagePolicy.policy_id)), + ]; + + const hostedAgentPolicies: string[] = []; + for (const agentPolicyId of uniqueAgentPolicyIds) { + try { await validateIsNotHostedPolicy( soClient, - packagePolicy?.policy_id, + agentPolicyId, options?.force, 'Cannot remove integrations of hosted agent policy' ); + } catch (e) { + hostedAgentPolicies.push(agentPolicyId); + } + } - const agentPolicy = await agentPolicyService - .get(soClient, packagePolicy.policy_id) - .catch((err) => { - if (SavedObjectsErrorHelpers.isNotFoundError(err)) { - appContextService - .getLogger() - .warn(`Agent policy ${packagePolicy.policy_id} not found`); - return null; - } - throw err; - }); + const deletePackagePolicy = async (id: string) => { + try { + const packagePolicy = packagePolicies.find((p) => p.id === id); - await soClient.delete(SAVED_OBJECT_TYPE, id); - if (agentPolicy && !options?.skipUnassignFromAgentPolicies) { - await agentPolicyService.bumpRevision(soClient, esClient, packagePolicy.policy_id, { - user: options?.user, - }); + if (!packagePolicy) { + throw new PackagePolicyNotFoundError( + `Saved object [ingest-package-policies/${id}] not found` + ); + } + + if (packagePolicy.is_managed && !options?.force) { + throw new PackagePolicyRestrictionRelatedError(`Cannot delete package policy ${id}`); } + + if (hostedAgentPolicies.includes(packagePolicy.policy_id)) { + throw new HostedAgentPolicyRestrictionRelatedError( + 'Cannot remove integrations of hosted agent policy' + ); + } + + // TODO: replace this with savedObject BulkDelete when following PR is merged + // https://github.com/elastic/kibana/pull/139680 + await soClient.delete(SAVED_OBJECT_TYPE, id); + result.push({ id, name: packagePolicy.name, @@ -606,6 +619,25 @@ class PackagePolicyService implements PackagePolicyServiceInterface { ...ingestErrorToResponseOptions(error), }); } + }; + + await pMap(ids, deletePackagePolicy, { concurrency: 1000 }); + + if (!options?.skipUnassignFromAgentPolicies) { + const uniquePolicyIdsR = [ + ...new Set(result.filter((r) => r.success && r.policy_id).map((r) => r.policy_id!)), + ]; + + const agentPolicies = await agentPolicyService.getByIDs(soClient, uniquePolicyIdsR); + + for (const policyId of uniquePolicyIdsR) { + const agentPolicy = agentPolicies.find((p) => p.id === policyId); + if (agentPolicy) { + await agentPolicyService.bumpRevision(soClient, esClient, policyId, { + user: options?.user, + }); + } + } } return result; From dfafa262c7caf20e7b5065220950cd1f72522531 Mon Sep 17 00:00:00 2001 From: Muhammad Ibragimov <53621505+mibragimov@users.noreply.github.com> Date: Tue, 13 Sep 2022 18:09:08 +0500 Subject: [PATCH 107/144] [Console] Update "Copy as cURL" to interpolate variables and strip request-body comments (#140262) * Interpolate variables and strip request-body comments in cURLs * Address CR change Co-authored-by: Muhammad Ibragimov <muhammad.ibragimov@elastic.co> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../application/components/console_menu.tsx | 16 ++- .../console/public/application/index.tsx | 9 +- .../models/sense_editor/sense_editor.test.js | 108 ++++++++++++++++++ .../models/sense_editor/sense_editor.ts | 40 +++++-- src/plugins/console/public/lib/utils/index.ts | 2 +- src/plugins/console/public/services/index.ts | 2 +- .../console/public/services/storage.ts | 3 + 7 files changed, 163 insertions(+), 17 deletions(-) diff --git a/src/plugins/console/public/application/components/console_menu.tsx b/src/plugins/console/public/application/components/console_menu.tsx index 159c0d600308f3..3f5113b3ac44f6 100644 --- a/src/plugins/console/public/application/components/console_menu.tsx +++ b/src/plugins/console/public/application/components/console_menu.tsx @@ -31,6 +31,7 @@ interface Props { interface State { isPopoverOpen: boolean; curlCode: string; + curlError: Error | null; } export class ConsoleMenu extends Component<Props, State> { @@ -40,14 +41,20 @@ export class ConsoleMenu extends Component<Props, State> { this.state = { curlCode: '', isPopoverOpen: false, + curlError: null, }; } mouseEnter = () => { if (this.state.isPopoverOpen) return; - this.props.getCurl().then((text) => { - this.setState({ curlCode: text }); - }); + this.props + .getCurl() + .then((text) => { + this.setState({ curlCode: text, curlError: null }); + }) + .catch((e) => { + this.setState({ curlError: e }); + }); }; async copyAsCurl() { @@ -69,6 +76,9 @@ export class ConsoleMenu extends Component<Props, State> { } async copyText(text: string) { + if (this.state.curlError) { + throw this.state.curlError; + } if (window.navigator?.clipboard) { await window.navigator.clipboard.writeText(text); return; diff --git a/src/plugins/console/public/application/index.tsx b/src/plugins/console/public/application/index.tsx index e9f37c232eeaa8..1cf9a54210973b 100644 --- a/src/plugins/console/public/application/index.tsx +++ b/src/plugins/console/public/application/index.tsx @@ -19,7 +19,13 @@ import { import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import { KibanaThemeProvider } from '../shared_imports'; -import { createStorage, createHistory, createSettings, AutocompleteInfo } from '../services'; +import { + createStorage, + createHistory, + createSettings, + AutocompleteInfo, + setStorage, +} from '../services'; import { createUsageTracker } from '../services/tracker'; import * as localStorageObjectClient from '../lib/local_storage_object_client'; import { Main } from './containers'; @@ -56,6 +62,7 @@ export function renderApp({ engine: window.localStorage, prefix: 'sense:', }); + setStorage(storage); const history = createHistory({ storage }); const settings = createSettings({ storage }); const objectStorageClient = localStorageObjectClient.create(storage); diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js index 4751d3ca29863e..c6f484e8f16972 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js @@ -15,6 +15,7 @@ import { URL } from 'url'; import { create } from './create'; import { XJson } from '@kbn/es-ui-shared-plugin/public'; import editorInput1 from './__fixtures__/editor_input1.txt'; +import { setStorage, createStorage } from '../../../services'; const { collapseLiteralStrings } = XJson; @@ -22,6 +23,7 @@ describe('Editor', () => { let input; let oldUrl; let olldWindow; + let storage; beforeEach(function () { // Set up our document body @@ -43,12 +45,18 @@ describe('Editor', () => { origin: 'http://localhost:5620', }, }); + storage = createStorage({ + engine: global.window.localStorage, + prefix: 'console_test', + }); + setStorage(storage); }); afterEach(function () { global.URL = oldUrl; global.window = olldWindow; $(input.getCoreEditor().getContainer()).hide(); input.autocomplete._test.addChangeListener(); + setStorage(null); }); let testCount = 0; @@ -506,4 +514,104 @@ curl -XPOST "http://localhost:9200/_sql?format=txt" -H "kbn-xsrf: reporting" -H ` curl -XGET "http://localhost:5620/api/spaces/space" -H \"kbn-xsrf: reporting\"`.trim() ); + + describe('getRequestsAsCURL', () => { + it('should return empty string if no requests', async () => { + input?.getCoreEditor().setValue('', false); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 1 }, + }); + expect(curl).toEqual(''); + }); + + it('should replace variables in the URL', async () => { + storage.set('variables', [{ name: 'exampleVariableA', value: 'valueA' }]); + input?.getCoreEditor().setValue('GET ${exampleVariableA}', false); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 1 }, + }); + expect(curl).toContain('valueA'); + }); + + it('should replace variables in the body', async () => { + storage.set('variables', [{ name: 'exampleVariableB', value: 'valueB' }]); + console.log(storage.get('variables')); + input + ?.getCoreEditor() + .setValue('GET _search\n{\t\t"query": {\n\t\t\t"${exampleVariableB}": ""\n\t}\n}', false); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 6 }, + }); + expect(curl).toContain('valueB'); + }); + + it('should strip comments in the URL', async () => { + input?.getCoreEditor().setValue('GET _search // comment', false); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 6 }, + }); + expect(curl).not.toContain('comment'); + }); + + it('should strip comments in the body', async () => { + input + ?.getCoreEditor() + .setValue('{\n\t"query": {\n\t\t"match_all": {} // comment \n\t}\n}', false); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 8 }, + }); + console.log('curl', curl); + expect(curl).not.toContain('comment'); + }); + + it('should strip multi-line comments in the body', async () => { + input + ?.getCoreEditor() + .setValue('{\n\t"query": {\n\t\t"match_all": {} /* comment */\n\t}\n}', false); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 8 }, + }); + console.log('curl', curl); + expect(curl).not.toContain('comment'); + }); + + it('should replace multiple variables in the URL', async () => { + storage.set('variables', [ + { name: 'exampleVariableA', value: 'valueA' }, + { name: 'exampleVariableB', value: 'valueB' }, + ]); + input?.getCoreEditor().setValue('GET ${exampleVariableA}/${exampleVariableB}', false); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 1 }, + }); + expect(curl).toContain('valueA'); + expect(curl).toContain('valueB'); + }); + + it('should replace multiple variables in the body', async () => { + storage.set('variables', [ + { name: 'exampleVariableA', value: 'valueA' }, + { name: 'exampleVariableB', value: 'valueB' }, + ]); + input + ?.getCoreEditor() + .setValue( + 'GET _search\n{\t\t"query": {\n\t\t\t"${exampleVariableA}": "${exampleVariableB}"\n\t}\n}', + false + ); + const curl = await input.getRequestsAsCURL('http://localhost:9200', { + start: { lineNumber: 1 }, + end: { lineNumber: 6 }, + }); + expect(curl).toContain('valueA'); + expect(curl).toContain('valueB'); + }); + }); }); diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts index 50ee1cd1d262a1..ac2205205ab465 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.ts +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.ts @@ -7,7 +7,7 @@ */ import _ from 'lodash'; - +import { parse } from 'hjson'; import { XJson } from '@kbn/es-ui-shared-plugin/public'; import RowParser from '../../../lib/row_parser'; @@ -19,6 +19,8 @@ import { constructUrl } from '../../../lib/es/es'; import { CoreEditor, Position, Range } from '../../../types'; import { createTokenIterator } from '../../factories'; import createAutocompleter from '../../../lib/autocomplete/autocomplete'; +import { getStorage, StorageKeys } from '../../../services'; +import { DEFAULT_VARIABLES } from '../../../../common/constants'; const { collapseLiteralStrings } = XJson; @@ -474,7 +476,9 @@ export class SenseEditor { }, 25); getRequestsAsCURL = async (elasticsearchBaseUrl: string, range?: Range): Promise<string> => { - const requests = await this.getRequestsInRange(range, true); + const variables = getStorage().get(StorageKeys.VARIABLES, DEFAULT_VARIABLES); + let requests = await this.getRequestsInRange(range, true); + requests = utils.replaceVariables(requests, variables); const result = _.map(requests, (req) => { if (typeof req === 'string') { // no request block @@ -490,16 +494,30 @@ export class SenseEditor { // Append 'kbn-xsrf' header to bypass (XSRF/CSRF) protections let ret = `curl -X${method.toUpperCase()} "${url}" -H "kbn-xsrf: reporting"`; + if (data && data.length) { - ret += ` -H "Content-Type: application/json" -d'\n`; - const dataAsString = collapseLiteralStrings(data.join('\n')); - - // We escape single quoted strings that that are wrapped in single quoted strings - ret += dataAsString.replace(/'/g, "'\\''"); - if (data.length > 1) { - ret += '\n'; - } // end with a new line - ret += "'"; + const joinedData = data.join('\n'); + let dataAsString: string; + + try { + ret += ` -H "Content-Type: application/json" -d'\n`; + + if (utils.hasComments(joinedData)) { + // if there are comments in the data, we need to strip them out + const dataWithoutComments = parse(joinedData); + dataAsString = collapseLiteralStrings(JSON.stringify(dataWithoutComments, null, 2)); + } else { + dataAsString = collapseLiteralStrings(joinedData); + } + // We escape single quoted strings that are wrapped in single quoted strings + ret += dataAsString.replace(/'/g, "'\\''"); + if (data.length > 1) { + ret += '\n'; + } // end with a new line + ret += "'"; + } catch (e) { + throw new Error(`Error parsing data: ${e.message}`); + } } return ret; }); diff --git a/src/plugins/console/public/lib/utils/index.ts b/src/plugins/console/public/lib/utils/index.ts index 2495f63c7614f3..dfa513085019d8 100644 --- a/src/plugins/console/public/lib/utils/index.ts +++ b/src/plugins/console/public/lib/utils/index.ts @@ -130,7 +130,7 @@ export const replaceVariables = ( }); } - if (req.data.length) { + if (req.data && req.data.length) { if (bodyRegex.test(req.data[0])) { const data = req.data[0].replaceAll(bodyRegex, (match) => { // Sanitize variable name diff --git a/src/plugins/console/public/services/index.ts b/src/plugins/console/public/services/index.ts index 2447ab1438ba4f..d73c169fd647a5 100644 --- a/src/plugins/console/public/services/index.ts +++ b/src/plugins/console/public/services/index.ts @@ -7,7 +7,7 @@ */ export { createHistory, History } from './history'; -export { createStorage, Storage, StorageKeys } from './storage'; +export { createStorage, Storage, StorageKeys, setStorage, getStorage } from './storage'; export type { DevToolsSettings } from './settings'; export { createSettings, Settings, DEFAULT_SETTINGS } from './settings'; export { AutocompleteInfo, getAutocompleteInfo, setAutocompleteInfo } from './autocomplete'; diff --git a/src/plugins/console/public/services/storage.ts b/src/plugins/console/public/services/storage.ts index 4b4d051607b8dd..b38cc2925dfb1d 100644 --- a/src/plugins/console/public/services/storage.ts +++ b/src/plugins/console/public/services/storage.ts @@ -7,6 +7,7 @@ */ import { transform, keys, startsWith } from 'lodash'; +import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; type IStorageEngine = typeof window.localStorage; @@ -71,3 +72,5 @@ export class Storage { export function createStorage(deps: { engine: IStorageEngine; prefix: string }) { return new Storage(deps.engine, deps.prefix); } + +export const [getStorage, setStorage] = createGetterSetter<Storage>('storage'); From 2be75d572999fb703ba00261640daa65d791d921 Mon Sep 17 00:00:00 2001 From: Cristina Amico <criamico@users.noreply.github.com> Date: Tue, 13 Sep 2022 15:22:18 +0200 Subject: [PATCH 108/144] [Fleet] Display category badge besides integrations list searchbar (#140391) * [Fleet] Display category badge besides integrations list searchbar * Fix padding in button * Avoid clearing query when clearing category * Fix cypress test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../integration/integrations_real.spec.ts | 81 +++++++++++----- .../fleet/cypress/screens/integrations.ts | 8 +- .../epm/components/package_list_grid.tsx | 95 ++++++++++++------- .../epm/screens/home/category_facets.tsx | 1 + 4 files changed, 122 insertions(+), 63 deletions(-) diff --git a/x-pack/plugins/fleet/cypress/integration/integrations_real.spec.ts b/x-pack/plugins/fleet/cypress/integration/integrations_real.spec.ts index 34fa5b7af55ca5..c3bee2d758df0b 100644 --- a/x-pack/plugins/fleet/cypress/integration/integrations_real.spec.ts +++ b/x-pack/plugins/fleet/cypress/integration/integrations_real.spec.ts @@ -22,14 +22,49 @@ import { POLICIES_TAB, SETTINGS_TAB, UPDATE_PACKAGE_BTN, - INTEGRATIONS_SEARCHBAR_INPUT, + INTEGRATIONS_SEARCHBAR, SETTINGS, INTEGRATION_POLICIES_UPGRADE_CHECKBOX, + INTEGRATION_LIST, + getIntegrationCategories, } from '../screens/integrations'; import { LOADING_SPINNER, CONFIRM_MODAL } from '../screens/navigation'; import { ADD_PACKAGE_POLICY_BTN } from '../screens/fleet'; import { cleanupAgentPolicies } from '../tasks/cleanup'; +function setupIntegrations() { + cy.intercept( + '/api/fleet/epm/packages?*', + { + middleware: true, + }, + (req) => { + req.on('before:response', (res) => { + // force all API responses to not be cached + res.headers['cache-control'] = 'no-store'; + }); + } + ).as('packages'); + + navigateTo(INTEGRATIONS); + cy.wait('@packages'); +} + +it('should install integration without policy', () => { + cy.visit('/app/integrations/detail/tomcat/settings'); + + cy.getBySel(SETTINGS.INSTALL_ASSETS_BTN).click(); + cy.get('.euiCallOut').contains('This action will install 1 assets'); + cy.getBySel(CONFIRM_MODAL.CONFIRM_BUTTON).click(); + + cy.getBySel(LOADING_SPINNER).should('not.exist'); + + cy.getBySel(SETTINGS.UNINSTALL_ASSETS_BTN).click(); + cy.getBySel(CONFIRM_MODAL.CONFIRM_BUTTON).click(); + cy.getBySel(LOADING_SPINNER).should('not.exist'); + cy.getBySel(SETTINGS.INSTALL_ASSETS_BTN).should('exist'); +}); + describe('Add Integration - Real API', () => { const integration = 'apache'; @@ -41,29 +76,6 @@ describe('Add Integration - Real API', () => { cleanupAgentPolicies(); }); - function addAndVerifyIntegration() { - cy.intercept( - '/api/fleet/epm/packages?*', - { - middleware: true, - }, - (req) => { - req.on('before:response', (res) => { - // force all API responses to not be cached - res.headers['cache-control'] = 'no-store'; - }); - } - ).as('packages'); - - navigateTo(INTEGRATIONS); - cy.wait('@packages'); - cy.getBySel(LOADING_SPINNER).should('not.exist'); - cy.getBySel(INTEGRATIONS_SEARCHBAR_INPUT).type('Apache'); - cy.getBySel(getIntegrationCard(integration)).click(); - addIntegration(); - cy.getBySel(INTEGRATION_NAME_LINK).contains('apache-1'); - } - it('should install integration without policy', () => { cy.visit('/app/integrations/detail/tomcat/settings'); @@ -80,7 +92,12 @@ describe('Add Integration - Real API', () => { }); it('should display Apache integration in the Policies list once installed ', () => { - addAndVerifyIntegration(); + setupIntegrations(); + cy.getBySel(LOADING_SPINNER).should('not.exist'); + cy.getBySel(INTEGRATIONS_SEARCHBAR.INPUT).clear().type('Apache'); + cy.getBySel(getIntegrationCard(integration)).click(); + addIntegration(); + cy.getBySel(INTEGRATION_NAME_LINK).contains('apache-1'); cy.getBySel(AGENT_POLICY_NAME_LINK).contains('Agent policy 1'); }); @@ -118,7 +135,7 @@ describe('Add Integration - Real API', () => { cy.getBySel(ADD_PACKAGE_POLICY_BTN).click(); cy.wait('@packages'); cy.getBySel(LOADING_SPINNER).should('not.exist'); - cy.getBySel(INTEGRATIONS_SEARCHBAR_INPUT).type('Apache'); + cy.getBySel(INTEGRATIONS_SEARCHBAR.INPUT).clear().type('Apache'); cy.getBySel(getIntegrationCard(integration)).click(); addIntegration({ useExistingPolicy: true }); cy.get('.euiBasicTable-loading').should('not.exist'); @@ -152,4 +169,16 @@ describe('Add Integration - Real API', () => { cy.getBySel(PACKAGE_VERSION).contains(newVersion); }); }); + + it('should filter integrations by category', () => { + setupIntegrations(); + cy.getBySel(getIntegrationCategories('aws')).click(); + cy.getBySel(INTEGRATIONS_SEARCHBAR.BADGE).contains('AWS').should('exist'); + cy.getBySel(INTEGRATION_LIST).find('.euiCard').should('have.length', 30); + + cy.getBySel(INTEGRATIONS_SEARCHBAR.INPUT).clear().type('Cloud'); + cy.getBySel(INTEGRATION_LIST).find('.euiCard').should('have.length', 3); + cy.getBySel(INTEGRATIONS_SEARCHBAR.REMOVE_BADGE_BUTTON).click(); + cy.getBySel(INTEGRATIONS_SEARCHBAR.BADGE).should('not.exist'); + }); }); diff --git a/x-pack/plugins/fleet/cypress/screens/integrations.ts b/x-pack/plugins/fleet/cypress/screens/integrations.ts index 3915c6600baaa0..63b13d8ff7fd3a 100644 --- a/x-pack/plugins/fleet/cypress/screens/integrations.ts +++ b/x-pack/plugins/fleet/cypress/screens/integrations.ts @@ -23,7 +23,12 @@ export const LATEST_VERSION = 'epmSettings.latestVersionTitle'; export const INSTALLED_VERSION = 'epmSettings.installedVersionTitle'; export const PACKAGE_VERSION = 'packageVersionText'; -export const INTEGRATIONS_SEARCHBAR_INPUT = 'epmList.searchBar'; +export const INTEGRATION_LIST = 'epmList.integrationCards'; +export const INTEGRATIONS_SEARCHBAR = { + INPUT: 'epmList.searchBar', + BADGE: 'epmList.categoryBadge', + REMOVE_BADGE_BUTTON: 'epmList.categoryBadge.closeBtn', +}; export const SETTINGS = { INSTALL_ASSETS_BTN: 'installAssetsButton', @@ -33,3 +38,4 @@ export const SETTINGS = { export const INTEGRATION_POLICIES_UPGRADE_CHECKBOX = 'epmDetails.upgradePoliciesCheckbox'; export const getIntegrationCard = (integration: string) => `integration-card:epr:${integration}`; +export const getIntegrationCategories = (category: string) => `epmList.categories.${category}`; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx index 98efc91cfc34c6..e360f615ad3698 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/components/package_list_grid.tsx @@ -15,9 +15,11 @@ import { EuiLink, EuiSpacer, EuiTitle, - EuiSearchBar, + EuiFieldSearch, EuiText, - EuiBadge, + useEuiTheme, + EuiIcon, + EuiScreenReaderOnly, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -69,6 +71,7 @@ export const PackageListGrid: FunctionComponent<Props> = ({ const menuRef = useRef<HTMLDivElement>(null); const [isSticky, setIsSticky] = useState(false); const [windowScrollY] = useState(window.scrollY); + const { euiTheme } = useEuiTheme(); useEffect(() => { const menuRefCurrent = menuRef.current; @@ -81,17 +84,10 @@ export const PackageListGrid: FunctionComponent<Props> = ({ return () => window.removeEventListener('scroll', onScroll); }, [windowScrollY, isSticky]); - const onQueryChange = ({ - queryText, - error, - }: { - queryText: string; - error: { message: string } | null; - }) => { - if (!error) { - onSearchChange(queryText); - setSearchTerm(queryText); - } + const onQueryChange = (e: any) => { + const queryText = e.target.value; + setSearchTerm(queryText); + onSearchChange(queryText); }; const resetQuery = () => { @@ -128,37 +124,64 @@ export const PackageListGrid: FunctionComponent<Props> = ({ <> {featuredList} <div ref={menuRef}> - <EuiFlexGroup alignItems="flexStart" gutterSize="xl"> + <EuiFlexGroup + alignItems="flexStart" + gutterSize="xl" + data-test-subj="epmList.integrationCards" + > <EuiFlexItem grow={1} className={isSticky ? 'kbnStickyMenu' : ''}> {controlsContent} </EuiFlexItem> <EuiFlexItem grow={5}> - <EuiSearchBar - query={searchTerm || undefined} - box={{ - 'data-test-subj': 'epmList.searchBar', - placeholder: i18n.translate('xpack.fleet.epmList.searchPackagesPlaceholder', { - defaultMessage: 'Search for integrations', - }), - incremental: true, - }} - onChange={onQueryChange} - toolsRight={ + <EuiFieldSearch + data-test-subj="epmList.searchBar" + placeholder={i18n.translate('xpack.fleet.epmList.searchPackagesPlaceholder', { + defaultMessage: 'Search for integrations', + })} + value={searchTerm} + onChange={(e) => onQueryChange(e)} + isClearable={true} + incremental={true} + fullWidth={true} + prepend={ selectedCategoryTitle ? ( - <div> - <EuiBadge - color="accent" - iconType="cross" - iconSide="right" - iconOnClick={() => { + <EuiText + data-test-subj="epmList.categoryBadge" + size="xs" + style={{ + display: 'flex', + alignItems: 'center', + fontWeight: euiTheme.font.weight.bold, + backgroundColor: euiTheme.colors.lightestShade, + }} + > + <EuiScreenReaderOnly> + <span>Searching category: </span> + </EuiScreenReaderOnly> + {selectedCategoryTitle} + <button + data-test-subj="epmList.categoryBadge.closeBtn" + onClick={() => { setSelectedCategory(''); }} - iconOnClickAriaLabel="Remove category" - data-test-sub="epmList.categoryBadge" + aria-label="Remove filter" + style={{ + padding: euiTheme.size.xs, + paddingTop: '2px', + }} > - {selectedCategoryTitle} - </EuiBadge> - </div> + <EuiIcon + type="cross" + color="text" + size="s" + style={{ + width: 'auto', + padding: 0, + backgroundColor: euiTheme.colors.lightestShade, + }} + /> + </button> + </EuiText> ) : undefined } /> diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/category_facets.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/category_facets.tsx index 573701ae9a6fb1..9f88e2c391b3d6 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/category_facets.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/category_facets.tsx @@ -64,6 +64,7 @@ export function CategoryFacets({ categories.map((category) => { return ( <EuiFacetButton + data-test-subj={`epmList.categories.${category.id}`} isSelected={category.id === selectedCategory} key={category.id} id={category.id} From 0b908db86ab8aba0e4deb14973e151f701d855b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= <david.sanchezsoler@elastic.co> Date: Tue, 13 Sep 2022 15:32:06 +0200 Subject: [PATCH 109/144] Adds policy generic error from agent components in fleet agent details (#140594) --- .../package_action_formatter.ts | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts index 57117c9b1397c9..f7796f8ef4c5c6 100644 --- a/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts +++ b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action_formatter.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import type { DocLinks } from '@kbn/doc-links'; -type PackageActions = 'es_connection'; +type PackageActions = 'es_connection' | 'policy_failure'; export const titles = Object.freeze( new Map<PackageActions, string>([ @@ -18,6 +18,15 @@ export const titles = Object.freeze( defaultMessage: 'Elasticsearch connection failure', }), ], + [ + 'policy_failure', + i18n.translate( + 'xpack.securitySolution.endpoint.details.packageActions.policy_failure.title', + { + defaultMessage: 'Policy response failure', + } + ), + ], ]) ); @@ -33,6 +42,16 @@ export const descriptions = Object.freeze( } ), ], + [ + 'policy_failure', + i18n.translate( + 'xpack.securitySolution.endpoint.details.packageActions.policy_failure.description', + { + defaultMessage: + 'The Endpoint did not apply the Policy correctly. Expand the Policy response above for more details.', + } + ), + ], ]) ); @@ -68,12 +87,16 @@ export class PackageActionFormatter { } public get linkUrl(): string { - return this.docLinks[this.key]; + return this.docLinks[ + this.key as keyof DocLinks['securitySolution']['packageActionTroubleshooting'] + ]; } private getKeyFromErrorCode(code: number): PackageActions { if (code === 123) { return 'es_connection'; + } else if (code === 124) { + return 'policy_failure'; } else { throw new Error(`Invalid error code ${code}`); } From 7e90e71aaa3329c5d6c133337be30631c3383cf3 Mon Sep 17 00:00:00 2001 From: Baturalp Gurdin <9674241+suchcodemuchwow@users.noreply.github.com> Date: Tue, 13 Sep 2022 16:34:03 +0300 Subject: [PATCH 110/144] skip flaky jest suite (#140618) --- .../pages/endpoint_hosts/view/components/search_bar.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx index eb651d8aedd12c..57611fcdf24842 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/components/search_bar.test.tsx @@ -16,7 +16,8 @@ import { fireEvent } from '@testing-library/dom'; import { uiQueryParams } from '../../store/selectors'; import type { EndpointIndexUIQueryParams } from '../../types'; -describe('when rendering the endpoint list `AdminSearchBar`', () => { +// FLAKY: https://github.com/elastic/kibana/issues/140618 +describe.skip('when rendering the endpoint list `AdminSearchBar`', () => { let render: ( urlParams?: EndpointIndexUIQueryParams ) => Promise<ReturnType<AppContextTestRender['render']>>; From 21aa27c8a84b090f1e011516b9f941ec0faf0a83 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger <walter.rafelsberger@elastic.co> Date: Tue, 13 Sep 2022 15:35:34 +0200 Subject: [PATCH 111/144] [ML] Fix cross-boundary imports. (#140470) Fix violations for cross-boundary imports. --- x-pack/plugins/ml/__mocks__/shared_imports.ts | 8 -------- .../create_analytics_button.test.tsx | 2 -- .../hooks/use_create_analytics_form/reducer.ts | 8 ++++++-- .../edit_job_flyout/edit_job_flyout.js | 4 +++- .../components/ml_job_editor/ml_job_editor.tsx | 11 +++++------ .../json_editor_flyout/json_editor_flyout.tsx | 4 +++- x-pack/plugins/ml/shared_imports.ts | 17 ----------------- x-pack/plugins/ml/tsconfig.json | 1 - 8 files changed, 17 insertions(+), 38 deletions(-) delete mode 100644 x-pack/plugins/ml/__mocks__/shared_imports.ts delete mode 100644 x-pack/plugins/ml/shared_imports.ts diff --git a/x-pack/plugins/ml/__mocks__/shared_imports.ts b/x-pack/plugins/ml/__mocks__/shared_imports.ts deleted file mode 100644 index 43494fea6992a4..00000000000000 --- a/x-pack/plugins/ml/__mocks__/shared_imports.ts +++ /dev/null @@ -1,8 +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. - */ - -export const XJsonMode = jest.fn(); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_button/create_analytics_button.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_button/create_analytics_button.test.tsx index c77a254be2f10d..9b3f86070a6cb9 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_button/create_analytics_button.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/create_analytics_button/create_analytics_button.test.tsx @@ -10,8 +10,6 @@ import React from 'react'; import { CreateAnalyticsButton } from './create_analytics_button'; -jest.mock('../../../../../../../shared_imports'); - describe('Data Frame Analytics: <CreateAnalyticsButton />', () => { test('Minimal initialization', () => { const wrapper = mount( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts index 58a471b4e72468..aa25bf2c8eb3dd 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/reducer.ts @@ -7,12 +7,14 @@ import { i18n } from '@kbn/i18n'; import { memoize, isEqual } from 'lodash'; + // @ts-ignore import numeral from '@elastic/numeral'; + import { indexPatterns } from '@kbn/data-plugin/public'; -import { isValidIndexName } from '../../../../../../../common/util/es_utils'; +import { XJson } from '@kbn/es-ui-shared-plugin/public'; -import { collapseLiteralStrings } from '../../../../../../../shared_imports'; +import { isValidIndexName } from '../../../../../../../common/util/es_utils'; import { Action, ACTION } from './actions'; import { @@ -48,6 +50,8 @@ import { } from '../../../../common/analytics'; import { isAdvancedConfig } from '../../components/action_clone/clone_action_name'; +const { collapseLiteralStrings } = XJson; + const mmlAllowedUnitsStr = `${ALLOWED_DATA_UNITS.slice(0, ALLOWED_DATA_UNITS.length - 1).join( ', ' )} or ${[...ALLOWED_DATA_UNITS].pop()}`; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js index 4fa5cdcb7c9f71..9100b7ffa03ab6 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/edit_job_flyout.js @@ -32,11 +32,13 @@ import { validateModelMemoryLimit, validateGroupNames, isValidCustomUrls } from import { toastNotificationServiceProvider } from '../../../../services/toast_notification_service'; import { ml } from '../../../../services/ml_api_service'; import { withKibana } from '@kbn/kibana-react-plugin/public'; -import { collapseLiteralStrings } from '../../../../../../shared_imports'; +import { XJson } from '@kbn/es-ui-shared-plugin/public'; import { DATAFEED_STATE, JOB_STATE } from '../../../../../../common/constants/states'; import { isManagedJob } from '../../../jobs_utils'; import { ManagedJobsWarningCallout } from '../confirm_modals/managed_jobs_warning_callout'; +const { collapseLiteralStrings } = XJson; + export class EditJobFlyoutUI extends Component { _initialJobFormState = null; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx index 631b9162025056..bbe91f77a72047 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/ml_job_editor/ml_job_editor.tsx @@ -6,13 +6,12 @@ */ import React, { FC } from 'react'; +import { XJsonMode } from '@kbn/ace'; -import { - expandLiteralStrings, - XJsonMode, - EuiCodeEditor, - EuiCodeEditorProps, -} from '../../../../../../shared_imports'; +import { EuiCodeEditor, XJson } from '@kbn/es-ui-shared-plugin/public'; +import type { EuiCodeEditorProps } from '@kbn/es-ui-shared-plugin/public'; + +const { expandLiteralStrings } = XJson; export const ML_EDITOR_MODE = { TEXT: 'text', JSON: 'json', XJSON: new XJsonMode() }; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx index 5b164623004460..b9e77a3a5f2732 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/common/json_editor_flyout/json_editor_flyout.tsx @@ -20,7 +20,7 @@ import { EuiSpacer, EuiCallOut, } from '@elastic/eui'; -import { collapseLiteralStrings } from '../../../../../../../../shared_imports'; +import { XJson } from '@kbn/es-ui-shared-plugin/public'; import { CombinedJob, Datafeed } from '../../../../../../../../common/types/anomaly_detection_jobs'; import { ML_EDITOR_MODE, MLJobEditor } from '../../../../../jobs_list/components/ml_job_editor'; import { isValidJson } from '../../../../../../../../common/util/validation_utils'; @@ -29,6 +29,8 @@ import { isAdvancedJobCreator } from '../../../../common/job_creator'; import { DatafeedPreview } from '../datafeed_preview_flyout'; import { useToastNotificationService } from '../../../../../../services/toast_notification_service'; +const { collapseLiteralStrings } = XJson; + export enum EDITOR_MODE { HIDDEN, READONLY, diff --git a/x-pack/plugins/ml/shared_imports.ts b/x-pack/plugins/ml/shared_imports.ts deleted file mode 100644 index 25f78cce556118..00000000000000 --- a/x-pack/plugins/ml/shared_imports.ts +++ /dev/null @@ -1,17 +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. - */ - -// eslint-disable-next-line @kbn/imports/no_boundary_crossing -export { EuiCodeEditor } from '@kbn/es-ui-shared-plugin/public'; -export type { EuiCodeEditorProps } from '@kbn/es-ui-shared-plugin/public'; - -// eslint-disable-next-line @kbn/imports/no_boundary_crossing -import { XJson } from '@kbn/es-ui-shared-plugin/public'; -const { collapseLiteralStrings, expandLiteralStrings } = XJson; - -export { XJsonMode } from '@kbn/ace'; -export { collapseLiteralStrings, expandLiteralStrings }; diff --git a/x-pack/plugins/ml/tsconfig.json b/x-pack/plugins/ml/tsconfig.json index 55651e2f811657..a99bc950ca4458 100644 --- a/x-pack/plugins/ml/tsconfig.json +++ b/x-pack/plugins/ml/tsconfig.json @@ -11,7 +11,6 @@ "public/**/*", "server/**/*", "__mocks__/**/*", - "shared_imports.ts", "../../../typings/**/*", // have to declare *.json explicitly due to https://github.com/microsoft/TypeScript/issues/25636 "public/**/*.json", From acac4ca970fdc2f1f73ea376f59f0c8f0fe55d71 Mon Sep 17 00:00:00 2001 From: Bhavya RM <bhavya@elastic.co> Date: Tue, 13 Sep 2022 09:40:42 -0400 Subject: [PATCH 112/144] timepicker TSVB refactoring (#140557) --- x-pack/test/functional/apps/rollup_job/tsvb.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/test/functional/apps/rollup_job/tsvb.js b/x-pack/test/functional/apps/rollup_job/tsvb.js index 4ef918aab09e4d..957b33618d9cfb 100644 --- a/x-pack/test/functional/apps/rollup_job/tsvb.js +++ b/x-pack/test/functional/apps/rollup_job/tsvb.js @@ -21,6 +21,8 @@ export default function ({ getService, getPageObjects }) { 'visualBuilder', 'timePicker', ]); + const fromTime = 'Oct 15, 2019 @ 00:00:01.000'; + const toTime = 'Oct 15, 2019 @ 19:31:44.000'; describe('tsvb integration', function () { //Since rollups can only be created once with the same name (even if you delete it), @@ -40,10 +42,11 @@ export default function ({ getService, getPageObjects }) { await kibanaServer.importExport.load( 'x-pack/test/functional/fixtures/kbn_archiver/rollup/rollup.json' ); - await kibanaServer.uiSettings.replace({ + await kibanaServer.uiSettings.update({ defaultIndex: 'rollup', + 'metrics:allowStringIndices': true, + 'timepicker:timeDefaults': `{ "from": "${fromTime}", "to": "${toTime}"}`, }); - await kibanaServer.uiSettings.update({ 'metrics:allowStringIndices': true }); }); it('create rollup tsvb', async () => { @@ -85,10 +88,6 @@ export default function ({ getService, getPageObjects }) { await PageObjects.visualBuilder.checkVisualBuilderIsPresent(); await PageObjects.visualBuilder.clickMetric(); await PageObjects.visualBuilder.checkMetricTabIsPresent(); - await PageObjects.timePicker.setAbsoluteRange( - 'Oct 15, 2019 @ 00:00:01.000', - 'Oct 15, 2019 @ 19:31:44.000' - ); await PageObjects.visualBuilder.clickPanelOptions('metric'); await PageObjects.visualBuilder.setIndexPatternValue(rollupTargetIndexName, false); await PageObjects.visualBuilder.selectIndexPatternTimeField('@timestamp'); @@ -112,6 +111,7 @@ export default function ({ getService, getPageObjects }) { 'x-pack/test/functional/fixtures/kbn_archiver/rollup/rollup.json' ); await kibanaServer.uiSettings.update({ 'metrics:allowStringIndices': false }); + await kibanaServer.uiSettings.replace({}); await security.testUser.restoreDefaults(); }); }); From 4255bac100d468de874a7c9d6d83e403b43e3aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Tue, 13 Sep 2022 09:47:09 -0400 Subject: [PATCH 113/144] APM: converting params to destructured obj (#140450) * service: converting params to destructured obj * transaction: convert params to destructuring obj * span/error: convert to destructure obj * error * browser * fixing span --- packages/kbn-apm-synthtrace/README.md | 4 +- .../kbn-apm-synthtrace/src/lib/apm/browser.ts | 30 +++++++-- .../src/lib/apm/instance.ts | 29 ++++++++- .../kbn-apm-synthtrace/src/lib/apm/service.ts | 10 ++- .../kbn-apm-synthtrace/src/lib/apm/span.ts | 42 +++++-------- .../src/scenarios/aws_lambda.ts | 6 +- .../src/scenarios/distributed_trace.ts | 22 ++++--- .../src/scenarios/high_throughput.ts | 24 ++++--- .../src/scenarios/low_throughput.ts | 26 +++++--- .../src/scenarios/many_services.ts | 26 +++++--- .../src/scenarios/simple_trace.ts | 20 ++++-- .../src/scenarios/span_links.ts | 20 +++--- .../src/test/event_dsl_behavior.test.ts | 10 ++- .../src/test/rate_per_minute.test.ts | 10 ++- .../test/scenarios/01_simple_trace.test.ts | 10 ++- .../scenarios/02_transaction_metrics.test.ts | 11 +++- .../03_span_destination_metrics.test.ts | 24 +++++-- .../scenarios/04_breakdown_metrics.test.ts | 21 ++++--- .../05_transactions_with_errors.test.ts | 16 ++--- .../scenarios/06_application_metrics.test.ts | 4 +- .../cypress/fixtures/synthtrace/opbeans.ts | 46 ++++++++++---- .../infrastructure/generate_data.ts | 20 ++++-- .../settings/agent_configurations.spec.ts | 16 +++-- .../read_only_user/errors/generate_data.ts | 28 ++++++--- .../service_inventory/generate_data.ts | 8 ++- .../header_filters/generate_data.ts | 16 +++-- .../aws_lambda/generate_data.ts | 8 ++- .../generate_span_links_data.ts | 62 +++++++++++++++---- .../tests/alerts/anomaly_alert.spec.ts | 6 +- .../tests/anomalies/anomaly_charts.spec.ts | 12 ++-- .../generate_data.ts | 8 ++- .../tests/cold_start/generate_data.ts | 8 ++- .../tests/data_view/static.spec.ts | 10 ++- .../tests/dependencies/generate_data.ts | 8 ++- .../dependencies/generate_operation_data.ts | 18 +++--- .../tests/dependencies/top_spans.spec.ts | 30 ++++++--- .../tests/error_rate/service_apis.spec.ts | 10 +-- .../tests/error_rate/service_maps.spec.ts | 16 +++-- .../tests/errors/error_group_list.spec.ts | 20 +++--- .../tests/errors/generate_data.ts | 12 ++-- .../generate_data.ts | 10 +-- .../generate_data.ts | 12 ++-- .../tests/infrastructure/generate_data.ts | 10 +-- .../tests/latency/service_apis.spec.ts | 8 +-- .../tests/latency/service_maps.spec.ts | 11 ++-- .../observability_overview.spec.ts | 12 ++-- .../service_nodes/get_service_nodes.spec.ts | 4 +- .../instances_main_statistics.spec.ts | 26 +++++--- .../services/error_groups/generate_data.ts | 20 +++--- .../get_service_node_metadata.spec.ts | 6 +- .../services/service_details/generate_data.ts | 8 ++- .../services/service_icons/generate_data.ts | 6 +- .../sorted_and_filtered_services.spec.ts | 21 +++++-- .../tests/services/throughput.spec.ts | 12 ++-- .../tests/services/top_services.spec.ts | 18 +++--- .../tests/span_links/data_generator.ts | 26 ++++---- .../storage_explorer_timeseries_chart.spec.ts | 18 ++++-- .../throughput/dependencies_apis.spec.ts | 30 ++++++--- .../tests/throughput/service_apis.spec.ts | 8 +-- .../tests/throughput/service_maps.spec.ts | 11 ++-- .../tests/traces/find_traces.spec.ts | 18 ++++-- .../tests/traces/trace_by_id.spec.ts | 14 +++-- ...actions_groups_detailed_statistics.spec.ts | 6 +- 63 files changed, 699 insertions(+), 343 deletions(-) diff --git a/packages/kbn-apm-synthtrace/README.md b/packages/kbn-apm-synthtrace/README.md index dcd50215c6a852..4aaaeee5b672c0 100644 --- a/packages/kbn-apm-synthtrace/README.md +++ b/packages/kbn-apm-synthtrace/README.md @@ -27,7 +27,7 @@ This library can currently be used in two ways: ```ts import { service, timerange, toElasticsearchOutput } from '@kbn/apm-synthtrace'; -const instance = service('synth-go', 'production', 'go').instance('instance-a'); +const instance = service({name: 'synth-go', environment: 'production', agentName: 'go'}).instance('instance-a'); const from = new Date('2021-01-01T12:00:00.000Z').getTime(); const to = new Date('2021-01-01T12:00:00.000Z').getTime(); @@ -37,7 +37,7 @@ const traceEvents = timerange(from, to) .rate(10) .flatMap((timestamp) => instance - .transaction('GET /api/product/list') + .transaction({transactionName: 'GET /api/product/list'}) .timestamp(timestamp) .duration(1000) .success() diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/browser.ts b/packages/kbn-apm-synthtrace/src/lib/apm/browser.ts index ebba6a0e89a696..89a1ac5d34a1d3 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/browser.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/browser.ts @@ -12,7 +12,13 @@ import { RumSpan } from './rum_span'; import { RumTransaction } from './rum_transaction'; export class Browser extends Entity<ApmFields> { - transaction(transactionName: string, transactionType: string = 'page-load') { + transaction({ + transactionName, + transactionType = 'page-load', + }: { + transactionName: string; + transactionType?: string; + }) { return new RumTransaction({ ...this.fields, 'transaction.name': transactionName, @@ -20,7 +26,15 @@ export class Browser extends Entity<ApmFields> { }); } - span(spanName: string, spanType: string, spanSubtype: string) { + span({ + spanName, + spanType, + spanSubtype, + }: { + spanName: string; + spanType: string; + spanSubtype: string; + }) { return new RumSpan({ ...this.fields, 'span.name': spanName, @@ -30,11 +44,19 @@ export class Browser extends Entity<ApmFields> { } } -export function browser(serviceName: string, production: string, userAgent: ApmUserAgentFields) { +export function browser({ + serviceName, + environment, + userAgent, +}: { + serviceName: string; + environment: string; + userAgent: ApmUserAgentFields; +}) { return new Browser({ 'agent.name': 'rum-js', 'service.name': serviceName, - 'service.environment': production, + 'service.environment': environment, ...userAgent, }); } diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts b/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts index d212c1f2cead0b..32a81de9f307a2 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/instance.ts @@ -14,7 +14,13 @@ import { Transaction } from './transaction'; import { ApmApplicationMetricFields, ApmFields } from './apm_fields'; export class Instance extends Entity<ApmFields> { - transaction(transactionName: string, transactionType = 'request') { + transaction({ + transactionName, + transactionType = 'request', + }: { + transactionName: string; + transactionType?: string; + }) { return new Transaction({ ...this.fields, 'transaction.name': transactionName, @@ -22,7 +28,16 @@ export class Instance extends Entity<ApmFields> { }); } - span(spanName: string, spanType: string, spanSubtype?: string, apmFields?: ApmFields) { + span({ + spanName, + spanType, + spanSubtype, + ...apmFields + }: { + spanName: string; + spanType: string; + spanSubtype?: string; + } & ApmFields) { return new Span({ ...this.fields, ...apmFields, @@ -32,7 +47,15 @@ export class Instance extends Entity<ApmFields> { }); } - error(message: string, type?: string, groupingName?: string) { + error({ + message, + type, + groupingName, + }: { + message: string; + type?: string; + groupingName?: string; + }) { return new ApmError({ ...this.fields, 'error.exception': [{ message, ...(type ? { type } : {}) }], diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/service.ts b/packages/kbn-apm-synthtrace/src/lib/apm/service.ts index ded149f0b6236e..0939535a87135e 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/service.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/service.ts @@ -20,7 +20,15 @@ export class Service extends Entity<ApmFields> { } } -export function service(name: string, environment: string, agentName: string) { +export function service({ + name, + environment, + agentName, +}: { + name: string; + environment: string; + agentName: string; +}) { return new Service({ 'service.name': name, 'service.environment': environment, diff --git a/packages/kbn-apm-synthtrace/src/lib/apm/span.ts b/packages/kbn-apm-synthtrace/src/lib/apm/span.ts index 388e65385e7dd8..a5795ae321478e 100644 --- a/packages/kbn-apm-synthtrace/src/lib/apm/span.ts +++ b/packages/kbn-apm-synthtrace/src/lib/apm/span.ts @@ -47,7 +47,7 @@ export function httpExitSpan({ }: { spanName: string; destinationUrl: string; -}): [string, string, string, ApmFields] { +}) { // origin: 'http://opbeans-go:3000', // host: 'opbeans-go:3000', // hostname: 'opbeans-go', @@ -57,39 +57,29 @@ export function httpExitSpan({ const spanType = 'external'; const spanSubType = 'http'; - return [ + return { spanName, spanType, spanSubType, - { - 'destination.address': destination.hostname, - 'destination.port': parseInt(destination.port, 10), - 'service.target.name': destination.host, - 'span.destination.service.name': destination.origin, - 'span.destination.service.resource': destination.host, - 'span.destination.service.type': 'external', - }, - ]; + 'destination.address': destination.hostname, + 'destination.port': parseInt(destination.port, 10), + 'service.target.name': destination.host, + 'span.destination.service.name': destination.origin, + 'span.destination.service.resource': destination.host, + 'span.destination.service.type': 'external', + }; } -export function dbExitSpan({ - spanName, - spanSubType, -}: { - spanName: string; - spanSubType?: string; -}): [string, string, string | undefined, ApmFields] { +export function dbExitSpan({ spanName, spanSubType }: { spanName: string; spanSubType?: string }) { const spanType = 'db'; - return [ + return { spanName, spanType, spanSubType, - { - 'service.target.type': spanSubType, - 'span.destination.service.name': spanSubType, - 'span.destination.service.resource': spanSubType, - 'span.destination.service.type': spanType, - }, - ]; + 'service.target.type': spanSubType, + 'span.destination.service.name': spanSubType, + 'span.destination.service.resource': spanSubType, + 'span.destination.service.type': spanType, + }; } diff --git a/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts b/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts index fa04d6e4f64651..2dcce23ab2a20b 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/aws_lambda.ts @@ -23,7 +23,9 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const range = timerange(from, to); const timestamps = range.ratePerMinute(180); - const instance = apm.service('lambda-python', ENVIRONMENT, 'python').instance('instance'); + const instance = apm + .service({ name: 'lambda-python', environment: ENVIRONMENT, agentName: 'python' }) + .instance('instance'); const traceEventsSetups = [ { functionName: 'lambda-python-1', coldStart: true }, @@ -33,7 +35,7 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const traceEvents = ({ functionName, coldStart }: typeof traceEventsSetups[0]) => { return timestamps.generator((timestamp) => instance - .transaction('GET /order/{id}') + .transaction({ transactionName: 'GET /order/{id}' }) .defaults({ 'service.runtime.name': 'AWS_Lambda_python3.8', 'cloud.provider': 'aws', diff --git a/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts index a87cbfe5ab4d3d..7834011afa69ae 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/distributed_trace.ts @@ -23,23 +23,27 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const transactionName = '240rpm/75% 1000ms'; const successfulTimestamps = range.interval('1s').rate(3); - const opbeansRum = apm.service('opbeans-rum', ENVIRONMENT, 'rum-js').instance('my-instance'); + const opbeansRum = apm + .service({ name: 'opbeans-rum', environment: ENVIRONMENT, agentName: 'rum-js' }) + .instance('my-instance'); const opbeansNode = apm - .service('opbeans-node', ENVIRONMENT, 'nodejs') + .service({ name: 'opbeans-node', environment: ENVIRONMENT, agentName: 'nodejs' }) + .instance('my-instance'); + const opbeansGo = apm + .service({ name: 'opbeans-go', environment: ENVIRONMENT, agentName: 'go' }) .instance('my-instance'); - const opbeansGo = apm.service('opbeans-go', ENVIRONMENT, 'go').instance('my-instance'); const traces = successfulTimestamps.generator((timestamp) => { // opbeans-rum return opbeansRum - .transaction(transactionName) + .transaction({ transactionName }) .duration(400) .timestamp(timestamp) .children( // opbeans-rum -> opbeans-node opbeansRum .span( - ...httpExitSpan({ + httpExitSpan({ spanName: 'GET /api/products/top', destinationUrl: 'http://opbeans-node:3000', }) @@ -50,14 +54,14 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { .children( // opbeans-node opbeansNode - .transaction('Initial transaction in opbeans-node') + .transaction({ transactionName: 'Initial transaction in opbeans-node' }) .duration(300) .timestamp(timestamp) .children( opbeansNode // opbeans-node -> opbeans-go .span( - ...httpExitSpan({ + httpExitSpan({ spanName: 'GET opbeans-go:3000', destinationUrl: 'http://opbeans-go:3000', }) @@ -69,12 +73,12 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { // opbeans-go opbeansGo - .transaction('Initial transaction in opbeans-go') + .transaction({ transactionName: 'Initial transaction in opbeans-go' }) .timestamp(timestamp) .duration(200) .children( opbeansGo - .span('custom_operation', 'custom') + .span({ spanName: 'custom_operation', spanType: 'custom' }) .timestamp(timestamp) .duration(100) .success() diff --git a/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts b/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts index 41b21df2e83e11..1b2ec3d64b0871 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/high_throughput.ts @@ -28,11 +28,11 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const instances = services.map((service, index) => apm - .service( - `${service}-${languages[index % languages.length]}`, - 'production', - languages[index % languages.length] - ) + .service({ + name: `${service}-${languages[index % languages.length]}`, + environment: 'production', + agentName: languages[index % languages.length], + }) .instance(`instance-${index}`) ); const entities = [ @@ -68,18 +68,22 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const generateError = index % random(mod, 9) === 0; const generateChildError = index % random(mod, 9) === 0; const span = instance - .transaction(url) + .transaction({ transactionName: url }) .timestamp(timestamp) .duration(duration) .children( instance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .duration(childDuration) .destination('elasticsearch') .timestamp(timestamp) .outcome(generateError && generateChildError ? 'failure' : 'success'), instance - .span('custom_operation', 'custom') + .span({ spanName: 'custom_operation', spanType: 'custom' }) .duration(remainderDuration) .success() .timestamp(timestamp + childDuration) @@ -88,7 +92,9 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { ? span.success() : span .failure() - .errors(instance.error(`No handler for ${url}`).timestamp(timestamp + 50)); + .errors( + instance.error({ message: `No handler for ${url}` }).timestamp(timestamp + 50) + ); }); return successfulTraceEvents; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts b/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts index d842a0650b423d..006a5074f7c1bd 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/low_throughput.ts @@ -32,11 +32,13 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const instances = services.map((service, index) => apm - .service( - `${services[index % services.length]}-${languages[index % languages.length]}-${index}`, - ENVIRONMENT, - languages[index % languages.length] - ) + .service({ + name: `${services[index % services.length]}-${ + languages[index % languages.length] + }-${index}`, + environment: ENVIRONMENT, + agentName: languages[index % languages.length], + }) .instance(`instance-${index}`) ); @@ -53,18 +55,22 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const generateError = index % random(mod, 9) === 0; const generateChildError = index % random(mod, 9) === 0; const span = instance - .transaction(url) + .transaction({ transactionName: url }) .timestamp(timestamp) .duration(duration) .children( instance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .duration(childDuration) .destination('elasticsearch') .timestamp(timestamp) .outcome(generateError && generateChildError ? 'failure' : 'success'), instance - .span('custom_operation', 'custom') + .span({ spanName: 'custom_operation', spanType: 'custom' }) .duration(remainderDuration) .success() .timestamp(timestamp + childDuration) @@ -73,7 +79,9 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { ? span.success() : span .failure() - .errors(instance.error(`No handler for ${url}`).timestamp(timestamp + 50)); + .errors( + instance.error({ message: `No handler for ${url}` }).timestamp(timestamp + 50) + ); }); return successfulTraceEvents; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts b/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts index 501d0e678f0f42..1829d46e172324 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/many_services.ts @@ -33,11 +33,13 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const instances = [...Array(numServices).keys()].map((index) => apm - .service( - `${services[index % services.length]}-${languages[index % languages.length]}-${index}`, - ENVIRONMENT, - languages[index % languages.length] - ) + .service({ + name: `${services[index % services.length]}-${ + languages[index % languages.length] + }-${index}`, + environment: ENVIRONMENT, + agentName: languages[index % languages.length], + }) .instance(`instance-${index}`) ); @@ -53,18 +55,22 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const generateError = random(1, 4) % 3 === 0; const generateChildError = random(0, 5) % 2 === 0; const span = instance - .transaction(url) + .transaction({ transactionName: url }) .timestamp(timestamp) .duration(duration) .children( instance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .duration(childDuration) .destination('elasticsearch') .timestamp(timestamp) .outcome(generateError && generateChildError ? 'failure' : 'success'), instance - .span('custom_operation', 'custom') + .span({ spanName: 'custom_operation', spanType: 'custom' }) .duration(remainderDuration) .success() .timestamp(timestamp + childDuration) @@ -73,7 +79,9 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { ? span.success() : span .failure() - .errors(instance.error(`No handler for ${url}`).timestamp(timestamp + 50)); + .errors( + instance.error({ message: `No handler for ${url}` }).timestamp(timestamp + 50) + ); }); return successfulTraceEvents; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts b/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts index f8444ab6e58790..8f3c84564787cf 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/simple_trace.ts @@ -31,24 +31,30 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const failedTimestamps = range.ratePerMinute(180); const instances = [...Array(numServices).keys()].map((index) => - apm.service(`opbeans-go-${index}`, ENVIRONMENT, 'go').instance('instance') + apm + .service({ name: `opbeans-go-${index}`, environment: ENVIRONMENT, agentName: 'go' }) + .instance('instance') ); const instanceSpans = (instance: Instance) => { const successfulTraceEvents = successfulTimestamps.generator((timestamp) => instance - .transaction(transactionName) + .transaction({ transactionName }) .timestamp(timestamp) .duration(1000) .success() .children( instance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .duration(1000) .success() .destination('elasticsearch') .timestamp(timestamp), instance - .span('custom_operation', 'custom') + .span({ spanName: 'custom_operation', spanType: 'custom' }) .duration(100) .success() .timestamp(timestamp) @@ -57,12 +63,14 @@ const scenario: Scenario<ApmFields> = async (runOptions: RunOptions) => { const failedTraceEvents = failedTimestamps.generator((timestamp) => instance - .transaction(transactionName) + .transaction({ transactionName }) .timestamp(timestamp) .duration(1000) .failure() .errors( - instance.error('[ResponseError] index_not_found_exception').timestamp(timestamp + 50) + instance + .error({ message: '[ResponseError] index_not_found_exception' }) + .timestamp(timestamp + 50) ) ); diff --git a/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts b/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts index 0c9250dcd16f7b..4267b6465b179f 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/span_links.ts @@ -35,7 +35,7 @@ const scenario: Scenario<ApmFields> = async () => { generate: ({ from, to }) => { const producerInternalOnlyInstance = apm - .service('producer-internal-only', ENVIRONMENT, 'go') + .service({ name: 'producer-internal-only', environment: ENVIRONMENT, agentName: 'go' }) .instance('instance-a'); const producerInternalOnlyEvents = timerange( new Date('2022-04-25T19:00:00.000Z'), @@ -45,13 +45,13 @@ const scenario: Scenario<ApmFields> = async () => { .rate(1) .generator((timestamp) => { return producerInternalOnlyInstance - .transaction('Transaction A') + .transaction({ transactionName: 'Transaction A' }) .timestamp(timestamp) .duration(1000) .success() .children( producerInternalOnlyInstance - .span('Span A', 'custom') + .span({ spanName: 'Span A', spanType: 'custom' }) .timestamp(timestamp + 50) .duration(100) .success() @@ -62,20 +62,20 @@ const scenario: Scenario<ApmFields> = async () => { const spanASpanLink = getSpanLinksFromEvents(producerInternalOnlyApmFields); const producerConsumerInstance = apm - .service('producer-consumer', ENVIRONMENT, 'java') + .service({ name: 'producer-consumer', environment: ENVIRONMENT, agentName: 'java' }) .instance('instance-b'); const producerConsumerEvents = timerange(from, to) .interval('1m') .rate(1) .generator((timestamp) => { return producerConsumerInstance - .transaction('Transaction B') + .transaction({ transactionName: 'Transaction B' }) .timestamp(timestamp) .duration(1000) .success() .children( producerConsumerInstance - .span('Span B', 'external') + .span({ spanName: 'Span B', spanType: 'external' }) .defaults({ 'span.links': shuffle([...generateExternalSpanLinks(), ...spanASpanLink]), }) @@ -88,19 +88,21 @@ const scenario: Scenario<ApmFields> = async () => { const producerConsumerApmFields = producerConsumerEvents.toArray(); const spanBSpanLink = getSpanLinksFromEvents(producerConsumerApmFields); - const consumerInstance = apm.service('consumer', ENVIRONMENT, 'ruby').instance('instance-c'); + const consumerInstance = apm + .service({ name: 'consumer', environment: ENVIRONMENT, agentName: 'ruby' }) + .instance('instance-c'); const consumerEvents = timerange(from, to) .interval('1m') .rate(1) .generator((timestamp) => { return consumerInstance - .transaction('Transaction C') + .transaction({ transactionName: 'Transaction C' }) .timestamp(timestamp) .duration(1000) .success() .children( consumerInstance - .span('Span C', 'external') + .span({ spanName: 'Span C', spanType: 'external' }) .defaults({ 'span.links': spanBSpanLink }) .timestamp(timestamp + 50) .duration(900) diff --git a/packages/kbn-apm-synthtrace/src/test/event_dsl_behavior.test.ts b/packages/kbn-apm-synthtrace/src/test/event_dsl_behavior.test.ts index 31a5ed02429d56..3cf1d8500e12d0 100644 --- a/packages/kbn-apm-synthtrace/src/test/event_dsl_behavior.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/event_dsl_behavior.test.ts @@ -19,7 +19,11 @@ describe('DSL invocations', () => { new Date('2021-01-01T00:00:00.000Z'), new Date('2021-01-01T00:15:00.000Z') ); - const javaService = apm.service('opbeans-java', 'production', 'java'); + const javaService = apm.service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }); const javaInstance = javaService.instance('instance-1'); let globalSeq = 0; @@ -28,13 +32,13 @@ describe('DSL invocations', () => { .rate(1) .generator((timestamp, index) => javaInstance - .transaction(`GET /api/product/${index}/${globalSeq++}`) + .transaction({ transactionName: `GET /api/product/${index}/${globalSeq++}` }) .duration(1000) .success() .timestamp(timestamp) .children( javaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ spanName: 'GET apm-*/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .success() .duration(900) .timestamp(timestamp + 50) diff --git a/packages/kbn-apm-synthtrace/src/test/rate_per_minute.test.ts b/packages/kbn-apm-synthtrace/src/test/rate_per_minute.test.ts index e40848ab9f47b0..5a100aa8a404d2 100644 --- a/packages/kbn-apm-synthtrace/src/test/rate_per_minute.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/rate_per_minute.test.ts @@ -19,7 +19,11 @@ describe('rate per minute calculations', () => { let events: Array<Record<string, any>>; beforeEach(() => { - const javaService = apm.service('opbeans-java', 'production', 'java'); + const javaService = apm.service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }); const javaInstance = javaService.instance('instance-1'); iterable = range @@ -27,13 +31,13 @@ describe('rate per minute calculations', () => { .rate(1) .generator((timestamp) => javaInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .success() .timestamp(timestamp) .children( javaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ spanName: 'GET apm-*/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .success() .duration(900) .timestamp(timestamp + 50) diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts b/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts index 8f405700fa2c1e..a278997ecdf731 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts @@ -16,7 +16,11 @@ describe('simple trace', () => { let events: Array<Record<string, any>>; beforeEach(() => { - const javaService = apm.service('opbeans-java', 'production', 'java'); + const javaService = apm.service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }); const javaInstance = javaService.instance('instance-1').containerId('instance-1'); const range = timerange( @@ -29,13 +33,13 @@ describe('simple trace', () => { .rate(1) .generator((timestamp) => javaInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .success() .timestamp(timestamp) .children( javaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ spanName: 'GET apm-*/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .success() .duration(900) .timestamp(timestamp + 50) diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts b/packages/kbn-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts index d7f60b2396cd0d..99715ab6998d62 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts @@ -16,7 +16,11 @@ describe('transaction metrics', () => { let events: Array<Record<string, any>>; beforeEach(() => { - const javaService = apm.service('opbeans-java', 'production', 'java'); + const javaService = apm.service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }); const javaInstance = javaService.instance('instance-1'); const range = timerange( @@ -25,7 +29,10 @@ describe('transaction metrics', () => { ); const span = (timestamp: number) => - javaInstance.transaction('GET /api/product/list').duration(1000).timestamp(timestamp); + javaInstance + .transaction({ transactionName: 'GET /api/product/list' }) + .duration(1000) + .timestamp(timestamp); const processor = new StreamProcessor<ApmFields>({ processors: [getTransactionMetrics], diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts b/packages/kbn-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts index 39c33e6486f692..f5c721221c3283 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts @@ -16,7 +16,11 @@ describe('span destination metrics', () => { let events: Array<Record<string, any>>; beforeEach(() => { - const javaService = apm.service('opbeans-java', 'production', 'java'); + const javaService = apm.service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }); const javaInstance = javaService.instance('instance-1'); const range = timerange( @@ -31,13 +35,17 @@ describe('span destination metrics', () => { .rate(25) .generator((timestamp) => javaInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .success() .timestamp(timestamp) .children( javaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .timestamp(timestamp) .duration(1000) .destination('elasticsearch') @@ -49,19 +57,23 @@ describe('span destination metrics', () => { .rate(50) .generator((timestamp) => javaInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .failure() .timestamp(timestamp) .children( javaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .timestamp(timestamp) .duration(1000) .destination('elasticsearch') .failure(), javaInstance - .span('custom_operation', 'app') + .span({ spanName: 'custom_operation', spanType: 'app' }) .timestamp(timestamp) .duration(500) .success() diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts b/packages/kbn-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts index 831ca790e57a65..731dea453058da 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts @@ -22,7 +22,11 @@ describe('breakdown metrics', () => { const INTERVALS = 6; beforeEach(() => { - const javaService = apm.service('opbeans-java', 'production', 'java'); + const javaService = apm.service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }); const javaInstance = javaService.instance('instance-1'); const start = new Date('2021-01-01T00:00:00.000Z'); @@ -34,15 +38,18 @@ describe('breakdown metrics', () => { .rate(LIST_RATE) .generator((timestamp) => javaInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .timestamp(timestamp) .duration(1000) .children( javaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ spanName: 'GET apm-*/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .timestamp(timestamp + 150) .duration(500), - javaInstance.span('GET foo', 'db', 'redis').timestamp(timestamp).duration(100) + javaInstance + .span({ spanName: 'GET foo', spanType: 'db', spanSubtype: 'redis' }) + .timestamp(timestamp) + .duration(100) ) ); @@ -51,17 +58,17 @@ describe('breakdown metrics', () => { .rate(ID_RATE) .generator((timestamp) => javaInstance - .transaction('GET /api/product/:id') + .transaction({ transactionName: 'GET /api/product/:id' }) .timestamp(timestamp) .duration(1000) .children( javaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ spanName: 'GET apm-*/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .duration(500) .timestamp(timestamp + 100) .children( javaInstance - .span('bar', 'external', 'http') + .span({ spanName: 'bar', spanType: 'external', spanSubtype: 'http' }) .timestamp(timestamp + 200) .duration(100) ) diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts b/packages/kbn-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts index b9b12aeab0754f..305c3ed2d88a4d 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts @@ -14,13 +14,15 @@ describe('transactions with errors', () => { const timestamp = new Date('2021-01-01T00:00:00.000Z').getTime(); beforeEach(() => { - instance = apm.service('opbeans-java', 'production', 'java').instance('instance'); + instance = apm + .service({ name: 'opbeans-java', environment: 'production', agentName: 'java' }) + .instance('instance'); }); it('generates error events', () => { const events = instance - .transaction('GET /api') + .transaction({ transactionName: 'GET /api' }) .timestamp(timestamp) - .errors(instance.error('test error').timestamp(timestamp)) + .errors(instance.error({ message: 'test error' }).timestamp(timestamp)) .serialize(); const errorEvents = events.filter((event) => event['processor.event'] === 'error'); @@ -39,9 +41,9 @@ describe('transactions with errors', () => { it('sets the transaction and trace id', () => { const [transaction, error] = instance - .transaction('GET /api') + .transaction({ transactionName: 'GET /api' }) .timestamp(timestamp) - .errors(instance.error('test error').timestamp(timestamp)) + .errors(instance.error({ message: 'test error' }).timestamp(timestamp)) .serialize(); const keys = ['transaction.id', 'trace.id', 'transaction.type']; @@ -55,9 +57,9 @@ describe('transactions with errors', () => { it('sets the error grouping key', () => { const [, error] = instance - .transaction('GET /api') + .transaction({ transactionName: 'GET /api' }) .timestamp(timestamp) - .errors(instance.error('test error').timestamp(timestamp)) + .errors(instance.error({ message: 'test error' }).timestamp(timestamp)) .serialize(); expect(error['error.grouping_name']).toEqual('test error'); diff --git a/packages/kbn-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts b/packages/kbn-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts index 7bae1e51f1ab3a..c9f33c2f237118 100644 --- a/packages/kbn-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts +++ b/packages/kbn-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts @@ -14,7 +14,9 @@ describe('application metrics', () => { const timestamp = new Date('2021-01-01T00:00:00.000Z').getTime(); beforeEach(() => { - instance = apm.service('opbeans-java', 'production', 'java').instance('instance'); + instance = apm + .service({ name: 'opbeans-java', environment: 'production', agentName: 'java' }) + .instance('instance'); }); it('generates application metricsets', () => { const events = instance diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts index 1be9873d25c4f5..bf8802c39f9f80 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/fixtures/synthtrace/opbeans.ts @@ -10,50 +10,70 @@ export function opbeans({ from, to }: { from: number; to: number }) { const range = timerange(from, to); const opbeansJava = apm - .service('opbeans-java', 'production', 'java') + .service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }) .instance('opbeans-java-prod-1') .podId('opbeans-java-prod-1-pod'); const opbeansNode = apm - .service('opbeans-node', 'production', 'nodejs') + .service({ + name: 'opbeans-node', + environment: 'production', + agentName: 'nodejs', + }) .instance('opbeans-node-prod-1'); - const opbeansRum = apm.browser( - 'opbeans-rum', - 'production', - apm.getChromeUserAgentDefaults() - ); + const opbeansRum = apm.browser({ + serviceName: 'opbeans-rum', + environment: 'production', + userAgent: apm.getChromeUserAgentDefaults(), + }); return range .interval('1s') .rate(1) .generator((timestamp) => [ opbeansJava - .transaction('GET /api/product') + .transaction({ transactionName: 'GET /api/product' }) .timestamp(timestamp) .duration(1000) .success() .errors( - opbeansJava.error('[MockError] Foo', `Exception`).timestamp(timestamp) + opbeansJava + .error({ message: '[MockError] Foo', type: `Exception` }) + .timestamp(timestamp) ) .children( opbeansJava - .span('SELECT * FROM product', 'db', 'postgresql') + .span({ + spanName: 'SELECT * FROM product', + spanType: 'db', + spanSubtype: 'postgresql', + }) .timestamp(timestamp) .duration(50) .success() .destination('postgresql') ), opbeansNode - .transaction('GET /api/product/:id') + .transaction({ transactionName: 'GET /api/product/:id' }) .timestamp(timestamp) .duration(500) .success(), opbeansNode - .transaction('Worker job', 'Worker') + .transaction({ + transactionName: 'Worker job', + transactionType: 'Worker', + }) .timestamp(timestamp) .duration(1000) .success(), - opbeansRum.transaction('/').timestamp(timestamp).duration(1000), + opbeansRum + .transaction({ transactionName: '/' }) + .timestamp(timestamp) + .duration(1000), ]); } diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/generate_data.ts index 52cf6b988f1a1d..dde70238377a77 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/generate_data.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/generate_data.ts @@ -9,21 +9,29 @@ import { apm, timerange } from '@kbn/apm-synthtrace'; export function generateData({ from, to }: { from: number; to: number }) { const range = timerange(from, to); const serviceRunsInContainerInstance = apm - .service('synth-go', 'production', 'go') + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceInstance = apm - .service('synth-java', 'production', 'java') + .service({ + name: 'synth-java', + environment: 'production', + agentName: 'java', + }) .instance('instance-b'); const serviceNoInfraDataInstance = apm - .service('synth-node', 'production', 'node') + .service({ + name: 'synth-node', + environment: 'production', + agentName: 'node', + }) .instance('instance-b'); return range.interval('1m').generator((timestamp) => { return [ serviceRunsInContainerInstance - .transaction('GET /apple 🍎') + .transaction({ transactionName: 'GET /apple 🍎' }) .defaults({ 'container.id': 'foo', 'host.hostname': 'bar', @@ -33,7 +41,7 @@ export function generateData({ from, to }: { from: number; to: number }) { .duration(1000) .success(), serviceInstance - .transaction('GET /banana 🍌') + .transaction({ transactionName: 'GET /banana 🍌' }) .defaults({ 'host.hostname': 'bar', }) @@ -41,7 +49,7 @@ export function generateData({ from, to }: { from: number; to: number }) { .duration(1000) .success(), serviceNoInfraDataInstance - .transaction('GET /banana 🍌') + .transaction({ transactionName: 'GET /banana 🍌' }) .timestamp(timestamp) .duration(1000) .success(), diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts index 23154492c9f441..5be39b4f082dc1 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts @@ -29,12 +29,20 @@ function generateData({ const range = timerange(from, to); const service1 = apm - .service(serviceName, 'production', 'java') + .service({ + name: serviceName, + environment: 'production', + agentName: 'java', + }) .instance('service-1-prod-1') .podId('service-1-prod-1-pod'); const service2 = apm - .service(serviceName, 'development', 'nodejs') + .service({ + name: serviceName, + environment: 'development', + agentName: 'nodejs', + }) .instance('opbeans-node-prod-1'); return range @@ -42,12 +50,12 @@ function generateData({ .rate(1) .generator((timestamp, index) => [ service1 - .transaction('GET /apple 🍎 ') + .transaction({ transactionName: 'GET /apple 🍎 ' }) .timestamp(timestamp) .duration(1000) .success(), service2 - .transaction('GET /banana 🍌') + .transaction({ transactionName: 'GET /banana 🍌' }) .timestamp(timestamp) .duration(500) .success(), diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts index 56978f03123a81..8f432305f2ba9f 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts @@ -10,12 +10,20 @@ export function generateData({ from, to }: { from: number; to: number }) { const range = timerange(from, to); const opbeansJava = apm - .service('opbeans-java', 'production', 'java') + .service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }) .instance('opbeans-java-prod-1') .podId('opbeans-java-prod-1-pod'); const opbeansNode = apm - .service('opbeans-node', 'production', 'nodejs') + .service({ + name: 'opbeans-node', + environment: 'production', + agentName: 'nodejs', + }) .instance('opbeans-node-prod-1'); return range @@ -23,17 +31,17 @@ export function generateData({ from, to }: { from: number; to: number }) { .rate(1) .generator((timestamp, index) => [ opbeansJava - .transaction('GET /apple 🍎 ') + .transaction({ transactionName: 'GET /apple 🍎 ' }) .timestamp(timestamp) .duration(1000) .success() .errors( opbeansJava - .error(`Error ${index}`, `exception ${index}`) + .error({ message: `Error ${index}`, type: `exception ${index}` }) .timestamp(timestamp) ), opbeansNode - .transaction('GET /banana 🍌') + .transaction({ transactionName: 'GET /banana 🍌' }) .timestamp(timestamp) .duration(500) .success(), @@ -52,7 +60,11 @@ export function generateErrors({ const range = timerange(from, to); const opbeansJava = apm - .service('opbeans-java', 'production', 'java') + .service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }) .instance('opbeans-java-prod-1') .podId('opbeans-java-prod-1-pod'); @@ -61,7 +73,7 @@ export function generateErrors({ .rate(1) .generator((timestamp, index) => [ opbeansJava - .transaction('GET /apple 🍎 ') + .transaction({ transactionName: 'GET /apple 🍎 ' }) .timestamp(timestamp) .duration(1000) .success() @@ -70,7 +82,7 @@ export function generateErrors({ .fill(0) .map((_, idx) => { return opbeansJava - .error(`Error ${idx}`, `exception ${idx}`) + .error({ message: `Error ${idx}`, type: `exception ${idx}` }) .timestamp(timestamp); }) ), diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/generate_data.ts index e3cdf7e8bbce88..3fd41b8a06fd06 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/generate_data.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/generate_data.ts @@ -19,7 +19,11 @@ export function generateMultipleServicesData({ .fill(0) .map((_, idx) => apm - .service(`${idx}`, 'production', 'nodejs') + .service({ + name: `${idx}`, + environment: 'production', + agentName: 'nodejs', + }) .instance('opbeans-node-prod-1') ); @@ -29,7 +33,7 @@ export function generateMultipleServicesData({ .generator((timestamp, index) => services.map((service) => service - .transaction('GET /foo') + .transaction({ transactionName: 'GET /foo' }) .timestamp(timestamp) .duration(500) .success() diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts index 243f1df257a4f9..6467768f75e28c 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts @@ -18,12 +18,20 @@ export function generateData({ const range = timerange(from, to); const service1 = apm - .service(specialServiceName, 'production', 'java') + .service({ + name: specialServiceName, + environment: 'production', + agentName: 'java', + }) .instance('service-1-prod-1') .podId('service-1-prod-1-pod'); const opbeansNode = apm - .service('opbeans-node', 'production', 'nodejs') + .service({ + name: 'opbeans-node', + environment: 'production', + agentName: 'nodejs', + }) .instance('opbeans-node-prod-1'); return range @@ -31,12 +39,12 @@ export function generateData({ .rate(1) .generator((timestamp) => [ service1 - .transaction('GET /apple 🍎 ') + .transaction({ transactionName: 'GET /apple 🍎 ' }) .timestamp(timestamp) .duration(1000) .success(), opbeansNode - .transaction('GET /banana 🍌') + .transaction({ transactionName: 'GET /banana 🍌' }) .timestamp(timestamp) .duration(500) .success(), diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts index bbd7553d1fa335..81d6aabf38165c 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts @@ -18,7 +18,11 @@ const dataConfig = { export function generateData({ start, end }: { start: number; end: number }) { const { rate, transaction, serviceName } = dataConfig; const instance = apm - .service(serviceName, 'production', 'python') + .service({ + name: serviceName, + environment: 'production', + agentName: 'python', + }) .instance('instance-a'); const traceEvents = timerange(start, end) @@ -26,7 +30,7 @@ export function generateData({ start, end }: { start: number; end: number }) { .rate(rate) .generator((timestamp) => instance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .defaults({ 'service.runtime.name': 'AWS_Lambda_python3.8', 'faas.coldstart': true, diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/generate_span_links_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/generate_span_links_data.ts index 9fd2cfe6eab0b4..d623ea664bc53c 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/generate_span_links_data.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/generate_span_links_data.ts @@ -10,7 +10,11 @@ import { SpanLink } from '../../../../../typings/es_schemas/raw/fields/span_link function getProducerInternalOnly() { const producerInternalOnlyInstance = apm - .service('producer-internal-only', 'production', 'go') + .service({ + name: 'producer-internal-only', + environment: 'production', + agentName: 'go', + }) .instance('instance a'); const events = timerange( @@ -21,13 +25,17 @@ function getProducerInternalOnly() { .rate(1) .generator((timestamp) => { return producerInternalOnlyInstance - .transaction(`Transaction A`) + .transaction({ transactionName: `Transaction A` }) .timestamp(timestamp) .duration(1000) .success() .children( producerInternalOnlyInstance - .span(`Span A`, 'external', 'http') + .span({ + spanName: `Span A`, + spanType: 'external', + spanSubtype: 'http', + }) .timestamp(timestamp + 50) .duration(100) .success() @@ -61,7 +69,11 @@ function getProducerInternalOnly() { function getProducerExternalOnly() { const producerExternalOnlyInstance = apm - .service('producer-external-only', 'production', 'java') + .service({ + name: 'producer-external-only', + environment: 'production', + agentName: 'java', + }) .instance('instance b'); const events = timerange( @@ -72,13 +84,17 @@ function getProducerExternalOnly() { .rate(1) .generator((timestamp) => { return producerExternalOnlyInstance - .transaction(`Transaction B`) + .transaction({ transactionName: `Transaction B` }) .timestamp(timestamp) .duration(1000) .success() .children( producerExternalOnlyInstance - .span(`Span B`, 'external', 'http') + .span({ + spanName: `Span B`, + spanType: 'external', + spanSubtype: 'http', + }) .defaults({ 'span.links': [ { trace: { id: 'trace#1' }, span: { id: 'span#1' } }, @@ -88,7 +104,11 @@ function getProducerExternalOnly() { .duration(100) .success(), producerExternalOnlyInstance - .span(`Span B.1`, 'external', 'http') + .span({ + spanName: `Span B.1`, + spanType: 'external', + spanSubtype: 'http', + }) .timestamp(timestamp + 50) .duration(100) .success() @@ -132,7 +152,11 @@ function getProducerConsumer({ producerInternalOnlySpanASpanLink?: SpanLink; }) { const producerConsumerInstance = apm - .service('producer-consumer', 'production', 'ruby') + .service({ + name: 'producer-consumer', + environment: 'production', + agentName: 'ruby', + }) .instance('instance c'); const events = timerange( @@ -143,7 +167,7 @@ function getProducerConsumer({ .rate(1) .generator((timestamp) => { return producerConsumerInstance - .transaction(`Transaction C`) + .transaction({ transactionName: `Transaction C` }) .defaults({ 'span.links': producerInternalOnlySpanASpanLink ? [producerInternalOnlySpanASpanLink] @@ -154,7 +178,11 @@ function getProducerConsumer({ .success() .children( producerConsumerInstance - .span(`Span C`, 'external', 'http') + .span({ + spanName: `Span C`, + spanType: 'external', + spanSubtype: 'http', + }) .timestamp(timestamp + 50) .duration(100) .success() @@ -209,7 +237,11 @@ function getConsumerMultiple({ producerConsumerTransactionCSpanLink?: SpanLink; }) { const consumerMultipleInstance = apm - .service('consumer-multiple', 'production', 'nodejs') + .service({ + name: 'consumer-multiple', + environment: 'production', + agentName: 'nodejs', + }) .instance('instance d'); const events = timerange( @@ -220,7 +252,7 @@ function getConsumerMultiple({ .rate(1) .generator((timestamp) => { return consumerMultipleInstance - .transaction(`Transaction D`) + .transaction({ transactionName: `Transaction D` }) .defaults({ 'span.links': producerInternalOnlySpanASpanLink && producerConsumerSpanCSpanLink @@ -235,7 +267,11 @@ function getConsumerMultiple({ .success() .children( consumerMultipleInstance - .span(`Span E`, 'external', 'http') + .span({ + spanName: `Span E`, + spanType: 'external', + spanSubtype: 'http', + }) .defaults({ 'span.links': producerExternalOnlySpanBSpanLink && diff --git a/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts index 43ba70cc100a15..53c5fec2bd5bfa 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts @@ -38,7 +38,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { let ruleId: string | undefined; before(async () => { - const serviceA = apm.service('a', 'production', 'java').instance('a'); + const serviceA = apm + .service({ name: 'a', environment: 'production', agentName: 'java' }) + .instance('a'); const events = timerange(new Date(start).getTime(), new Date(end).getTime()) .interval('1m') @@ -52,7 +54,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { return [ ...range(0, count).flatMap((_) => serviceA - .transaction('tx', 'request') + .transaction({ transactionName: 'tx' }) .timestamp(timestamp) .duration(duration) .outcome(outcome) diff --git a/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts b/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts index 0416a0124627af..80a5474ae41b24 100644 --- a/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts +++ b/x-pack/test/apm_api_integration/tests/anomalies/anomaly_charts.spec.ts @@ -101,9 +101,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { const NORMAL_RATE = 1; before(async () => { - const serviceA = apm.service('a', 'production', 'java').instance('a'); + const serviceA = apm + .service({ name: 'a', environment: 'production', agentName: 'java' }) + .instance('a'); - const serviceB = apm.service('b', 'development', 'go').instance('b'); + const serviceB = apm + .service({ name: 'b', environment: 'development', agentName: 'go' }) + .instance('b'); const events = timerange(new Date(start).getTime(), new Date(end).getTime()) .interval('1m') @@ -117,13 +121,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { return [ ...range(0, count).flatMap((_) => serviceA - .transaction('tx', 'request') + .transaction({ transactionName: 'tx', transactionType: 'request' }) .timestamp(timestamp) .duration(duration) .outcome(outcome) ), serviceB - .transaction('tx', 'Worker') + .transaction({ transactionName: 'tx', transactionType: 'Worker' }) .timestamp(timestamp) .duration(duration) .success(), diff --git a/x-pack/test/apm_api_integration/tests/cold_start/cold_start_by_transaction_name/generate_data.ts b/x-pack/test/apm_api_integration/tests/cold_start/cold_start_by_transaction_name/generate_data.ts index 4effd2ed23d7c3..51b3a198667b0b 100644 --- a/x-pack/test/apm_api_integration/tests/cold_start/cold_start_by_transaction_name/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/cold_start/cold_start_by_transaction_name/generate_data.ts @@ -27,14 +27,16 @@ export async function generateData({ warmStartRate: number; }) { const { transactionName, duration, serviceName } = dataConfig; - const instance = apm.service(serviceName, 'production', 'go').instance('instance-a'); + const instance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance('instance-a'); const traceEvents = timerange(start, end) .interval('1m') .rate(coldStartRate) .generator((timestamp) => instance - .transaction(transactionName) + .transaction({ transactionName }) .defaults({ 'faas.coldstart': true, }) @@ -48,7 +50,7 @@ export async function generateData({ .rate(warmStartRate) .generator((timestamp) => instance - .transaction(transactionName) + .transaction({ transactionName }) .defaults({ 'faas.coldstart': false, }) diff --git a/x-pack/test/apm_api_integration/tests/cold_start/generate_data.ts b/x-pack/test/apm_api_integration/tests/cold_start/generate_data.ts index 4baa9fd877f10f..b7169d3aedc54f 100644 --- a/x-pack/test/apm_api_integration/tests/cold_start/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/cold_start/generate_data.ts @@ -33,7 +33,9 @@ export async function generateData({ warmStartRate: number; }) { const { coldStartTransaction, warmStartTransaction, serviceName } = dataConfig; - const instance = apm.service(serviceName, 'production', 'go').instance('instance-a'); + const instance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance('instance-a'); const traceEvents = [ timerange(start, end) @@ -41,7 +43,7 @@ export async function generateData({ .rate(coldStartRate) .generator((timestamp) => instance - .transaction(coldStartTransaction.name) + .transaction({ transactionName: coldStartTransaction.name }) .defaults({ 'faas.coldstart': true, }) @@ -54,7 +56,7 @@ export async function generateData({ .rate(warmStartRate) .generator((timestamp) => instance - .transaction(warmStartTransaction.name) + .transaction({ transactionName: warmStartTransaction.name }) .defaults({ 'faas.coldstart': false, }) diff --git a/x-pack/test/apm_api_integration/tests/data_view/static.spec.ts b/x-pack/test/apm_api_integration/tests/data_view/static.spec.ts index a77a2e443b9d5e..11bb01d3ca7bb9 100644 --- a/x-pack/test/apm_api_integration/tests/data_view/static.spec.ts +++ b/x-pack/test/apm_api_integration/tests/data_view/static.spec.ts @@ -136,14 +136,20 @@ function generateApmData(synthtrace: ApmSynthtraceEsClient) { new Date('2021-10-01T00:01:00.000Z').getTime() ); - const instance = apm.service('multiple-env-service', 'production', 'go').instance('my-instance'); + const instance = apm + .service({ name: 'multiple-env-service', environment: 'production', agentName: 'go' }) + .instance('my-instance'); return synthtrace.index([ range .interval('1s') .rate(1) .generator((timestamp) => - instance.transaction('GET /api').timestamp(timestamp).duration(30).success() + instance + .transaction({ transactionName: 'GET /api' }) + .timestamp(timestamp) + .duration(30) + .success() ), ]); } diff --git a/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts b/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts index 1efab799963881..c7a5c43b05c05f 100644 --- a/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/dependencies/generate_data.ts @@ -30,7 +30,9 @@ export async function generateData({ start: number; end: number; }) { - const instance = apm.service('synth-go', 'production', 'go').instance('instance-a'); + const instance = apm + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) + .instance('instance-a'); const { rate, transaction, span } = dataConfig; await synthtraceEsClient.index( @@ -39,13 +41,13 @@ export async function generateData({ .rate(rate) .generator((timestamp) => instance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .timestamp(timestamp) .duration(transaction.duration) .success() .children( instance - .span(span.name, span.type, span.subType) + .span({ spanName: span.name, spanType: span.type, spanSubtype: span.subType }) .duration(transaction.duration) .success() .destination(span.destination) diff --git a/x-pack/test/apm_api_integration/tests/dependencies/generate_operation_data.ts b/x-pack/test/apm_api_integration/tests/dependencies/generate_operation_data.ts index 7724b5fe334b66..7537e310bff22b 100644 --- a/x-pack/test/apm_api_integration/tests/dependencies/generate_operation_data.ts +++ b/x-pack/test/apm_api_integration/tests/dependencies/generate_operation_data.ts @@ -27,8 +27,12 @@ export async function generateOperationData({ end: number; synthtraceEsClient: ApmSynthtraceEsClient; }) { - const synthGoInstance = apm.service('synth-go', 'production', 'go').instance('instance-a'); - const synthJavaInstance = apm.service('synth-java', 'development', 'java').instance('instance-a'); + const synthGoInstance = apm + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) + .instance('instance-a'); + const synthJavaInstance = apm + .service({ name: 'synth-java', environment: 'development', agentName: 'java' }) + .instance('instance-a'); const interval = timerange(start, end).interval('1m'); @@ -37,7 +41,7 @@ export async function generateOperationData({ .rate(generateOperationDataConfig.ES_SEARCH_UNKNOWN_RATE) .generator((timestamp) => synthGoInstance - .span('/_search', 'db', 'elasticsearch') + .span({ spanName: '/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .destination('elasticsearch') .timestamp(timestamp) .duration(generateOperationDataConfig.ES_SEARCH_DURATION) @@ -46,7 +50,7 @@ export async function generateOperationData({ .rate(generateOperationDataConfig.ES_SEARCH_SUCCESS_RATE) .generator((timestamp) => synthGoInstance - .span('/_search', 'db', 'elasticsearch') + .span({ spanName: '/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .destination('elasticsearch') .timestamp(timestamp) .success() @@ -56,7 +60,7 @@ export async function generateOperationData({ .rate(generateOperationDataConfig.ES_SEARCH_FAILURE_RATE) .generator((timestamp) => synthGoInstance - .span('/_search', 'db', 'elasticsearch') + .span({ spanName: '/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .destination('elasticsearch') .timestamp(timestamp) .failure() @@ -66,7 +70,7 @@ export async function generateOperationData({ .rate(generateOperationDataConfig.ES_BULK_RATE) .generator((timestamp) => synthJavaInstance - .span('/_bulk', 'db', 'elasticsearch') + .span({ spanName: '/_bulk', spanType: 'db', spanSubtype: 'elasticsearch' }) .destination('elasticsearch') .timestamp(timestamp) .duration(generateOperationDataConfig.ES_BULK_DURATION) @@ -75,7 +79,7 @@ export async function generateOperationData({ .rate(generateOperationDataConfig.REDIS_SET_RATE) .generator((timestamp) => synthJavaInstance - .span('SET', 'db', 'redis') + .span({ spanName: 'SET', spanType: 'db', spanSubtype: 'redis' }) .destination('redis') .timestamp(timestamp) .duration(generateOperationDataConfig.REDIS_SET_DURATION) diff --git a/x-pack/test/apm_api_integration/tests/dependencies/top_spans.spec.ts b/x-pack/test/apm_api_integration/tests/dependencies/top_spans.spec.ts index 06890c0b6fd592..e93af3051d4514 100644 --- a/x-pack/test/apm_api_integration/tests/dependencies/top_spans.spec.ts +++ b/x-pack/test/apm_api_integration/tests/dependencies/top_spans.spec.ts @@ -70,9 +70,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { 'Top dependency spans when data is loaded', { config: 'basic', archives: [] }, () => { - const javaInstance = apm.service('java', 'production', 'java').instance('instance-a'); + const javaInstance = apm + .service({ name: 'java', environment: 'production', agentName: 'java' }) + .instance('instance-a'); - const goInstance = apm.service('go', 'development', 'go').instance('instance-a'); + const goInstance = apm + .service({ name: 'go', environment: 'development', agentName: 'go' }) + .instance('instance-a'); before(async () => { await synthtraceEsClient.index([ @@ -81,40 +85,48 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(1) .generator((timestamp) => [ javaInstance - .span('without transaction', 'db', 'elasticsearch') + .span({ + spanName: 'without transaction', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .destination('elasticsearch') .duration(200) .timestamp(timestamp), javaInstance - .transaction('GET /api/my-endpoint') + .transaction({ transactionName: 'GET /api/my-endpoint' }) .duration(100) .timestamp(timestamp) .children( javaInstance - .span('/_search', 'db', 'elasticsearch') + .span({ spanName: '/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .destination('elasticsearch') .duration(100) .success() .timestamp(timestamp) ), goInstance - .transaction('GET /api/my-other-endpoint') + .transaction({ transactionName: 'GET /api/my-other-endpoint' }) .duration(100) .timestamp(timestamp) .children( goInstance - .span('/_search', 'db', 'elasticsearch') + .span({ spanName: '/_search', spanType: 'db', spanSubtype: 'elasticsearch' }) .destination('elasticsearch') .duration(50) .timestamp(timestamp) ), goInstance - .transaction('GET /api/my-other-endpoint') + .transaction({ transactionName: 'GET /api/my-other-endpoint' }) .duration(100) .timestamp(timestamp) .children( goInstance - .span('/_search', 'db', 'fake-elasticsearch') + .span({ + spanName: '/_search', + spanType: 'db', + spanSubtype: 'fake-elasticsearch', + }) .destination('fake-elasticsearch') .duration(50) .timestamp(timestamp) diff --git a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts index fe2f9c8cd2cf80..8b735b51d1e68a 100644 --- a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts +++ b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.spec.ts @@ -122,7 +122,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const GO_PROD_ID_ERROR_RATE = 50; before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const transactionNameProductList = 'GET /api/product/list'; @@ -134,7 +134,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_LIST_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductList) + .transaction({ transactionName: transactionNameProductList }) .timestamp(timestamp) .duration(1000) .success() @@ -144,7 +144,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_LIST_ERROR_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductList) + .transaction({ transactionName: transactionNameProductList }) .duration(1000) .timestamp(timestamp) .failure() @@ -154,7 +154,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_ID_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductId) + .transaction({ transactionName: transactionNameProductId }) .timestamp(timestamp) .duration(1000) .success() @@ -164,7 +164,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_ID_ERROR_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductId) + .transaction({ transactionName: transactionNameProductId }) .duration(1000) .timestamp(timestamp) .failure() diff --git a/x-pack/test/apm_api_integration/tests/error_rate/service_maps.spec.ts b/x-pack/test/apm_api_integration/tests/error_rate/service_maps.spec.ts index 8c14a203f78007..3610b240572aaf 100644 --- a/x-pack/test/apm_api_integration/tests/error_rate/service_maps.spec.ts +++ b/x-pack/test/apm_api_integration/tests/error_rate/service_maps.spec.ts @@ -68,7 +68,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const GO_PROD_ID_ERROR_RATE = 50; before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const transactionNameProductList = 'GET /api/product/list'; @@ -80,7 +80,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_LIST_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductList, 'Worker') + .transaction({ + transactionName: transactionNameProductList, + transactionType: 'Worker', + }) .timestamp(timestamp) .duration(1000) .success() @@ -90,7 +93,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_LIST_ERROR_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductList, 'Worker') + .transaction({ + transactionName: transactionNameProductList, + transactionType: 'Worker', + }) .duration(1000) .timestamp(timestamp) .failure() @@ -100,7 +106,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_ID_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductId) + .transaction({ transactionName: transactionNameProductId }) .timestamp(timestamp) .duration(1000) .success() @@ -110,7 +116,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_ID_ERROR_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductId) + .transaction({ transactionName: transactionNameProductId }) .duration(1000) .timestamp(timestamp) .failure() diff --git a/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts b/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts index 5156ed7f054786..534850d2cc927c 100644 --- a/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts +++ b/x-pack/test/apm_api_integration/tests/errors/error_group_list.spec.ts @@ -68,7 +68,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { }; before(async () => { - const serviceInstance = apm.service(serviceName, 'production', 'go').instance('instance-a'); + const serviceInstance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance('instance-a'); await synthtraceEsClient.index([ timerange(start, end) @@ -76,7 +78,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(appleTransaction.successRate) .generator((timestamp) => serviceInstance - .transaction(appleTransaction.name) + .transaction({ transactionName: appleTransaction.name }) .timestamp(timestamp) .duration(1000) .success() @@ -86,8 +88,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(appleTransaction.failureRate) .generator((timestamp) => serviceInstance - .transaction(appleTransaction.name) - .errors(serviceInstance.error('error 1', 'foo').timestamp(timestamp)) + .transaction({ transactionName: appleTransaction.name }) + .errors( + serviceInstance.error({ message: 'error 1', type: 'foo' }).timestamp(timestamp) + ) .duration(1000) .timestamp(timestamp) .failure() @@ -97,7 +101,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(bananaTransaction.successRate) .generator((timestamp) => serviceInstance - .transaction(bananaTransaction.name) + .transaction({ transactionName: bananaTransaction.name }) .timestamp(timestamp) .duration(1000) .success() @@ -107,8 +111,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(bananaTransaction.failureRate) .generator((timestamp) => serviceInstance - .transaction(bananaTransaction.name) - .errors(serviceInstance.error('error 2', 'bar').timestamp(timestamp)) + .transaction({ transactionName: bananaTransaction.name }) + .errors( + serviceInstance.error({ message: 'error 2', type: 'bar' }).timestamp(timestamp) + ) .duration(1000) .timestamp(timestamp) .failure() diff --git a/x-pack/test/apm_api_integration/tests/errors/generate_data.ts b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts index 75d80b85990317..dee5dce49076d5 100644 --- a/x-pack/test/apm_api_integration/tests/errors/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/errors/generate_data.ts @@ -31,7 +31,9 @@ export async function generateData({ start: number; end: number; }) { - const serviceGoProdInstance = apm.service(serviceName, 'production', 'go').instance('instance-a'); + const serviceGoProdInstance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance('instance-a'); const interval = '1m'; @@ -43,7 +45,7 @@ export async function generateData({ .rate(transaction.successRate) .generator((timestamp) => serviceGoProdInstance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .timestamp(timestamp) .duration(1000) .success() @@ -54,9 +56,11 @@ export async function generateData({ .rate(transaction.failureRate) .generator((timestamp) => serviceGoProdInstance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .errors( - serviceGoProdInstance.error(`Error ${index}`, transaction.name).timestamp(timestamp) + serviceGoProdInstance + .error({ message: `Error ${index}`, type: transaction.name }) + .timestamp(timestamp) ) .duration(1000) .timestamp(timestamp) diff --git a/x-pack/test/apm_api_integration/tests/errors/top_erroneous_transactions/generate_data.ts b/x-pack/test/apm_api_integration/tests/errors/top_erroneous_transactions/generate_data.ts index 6991c66e8eede2..60f0e09875dbc1 100644 --- a/x-pack/test/apm_api_integration/tests/errors/top_erroneous_transactions/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/errors/top_erroneous_transactions/generate_data.ts @@ -31,7 +31,9 @@ export async function generateData({ start: number; end: number; }) { - const serviceGoProdInstance = apm.service(serviceName, 'production', 'go').instance('instance-a'); + const serviceGoProdInstance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance('instance-a'); const interval = '1m'; @@ -43,7 +45,7 @@ export async function generateData({ .rate(transaction.successRate) .generator((timestamp) => serviceGoProdInstance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .timestamp(timestamp) .duration(1000) .success() @@ -54,10 +56,10 @@ export async function generateData({ .rate(transaction.failureRate) .generator((timestamp) => serviceGoProdInstance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .errors( serviceGoProdInstance - .error('Error 1', transaction.name, 'Error test') + .error({ message: 'Error 1', type: transaction.name, groupingName: 'Error test' }) .timestamp(timestamp) ) .duration(1000) diff --git a/x-pack/test/apm_api_integration/tests/errors/top_errors_for_transaction/generate_data.ts b/x-pack/test/apm_api_integration/tests/errors/top_errors_for_transaction/generate_data.ts index 3e37fc871405fa..e377b3c0db995b 100644 --- a/x-pack/test/apm_api_integration/tests/errors/top_errors_for_transaction/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/errors/top_errors_for_transaction/generate_data.ts @@ -31,7 +31,9 @@ export async function generateData({ start: number; end: number; }) { - const serviceGoProdInstance = apm.service(serviceName, 'production', 'go').instance('instance-a'); + const serviceGoProdInstance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance('instance-a'); const interval = '1m'; @@ -43,7 +45,7 @@ export async function generateData({ .rate(transaction.successRate) .generator((timestamp) => serviceGoProdInstance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .timestamp(timestamp) .duration(1000) .success() @@ -54,13 +56,13 @@ export async function generateData({ .rate(transaction.failureRate) .generator((timestamp) => serviceGoProdInstance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .errors( serviceGoProdInstance - .error(`Error 1 transaction ${transaction.name}`) + .error({ message: `Error 1 transaction ${transaction.name}` }) .timestamp(timestamp), serviceGoProdInstance - .error(`Error 2 transaction ${transaction.name}`) + .error({ message: `Error 2 transaction ${transaction.name}` }) .timestamp(timestamp) ) .duration(1000) diff --git a/x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts b/x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts index 5f4f80061ed2f2..5bab490b303a2c 100644 --- a/x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/infrastructure/generate_data.ts @@ -17,10 +17,12 @@ export async function generateData({ end: number; }) { const serviceRunsInContainerInstance = apm - .service('synth-go', 'production', 'go') + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) .instance('instance-a'); - const serviceInstance = apm.service('synth-java', 'production', 'java').instance('instance-b'); + const serviceInstance = apm + .service({ name: 'synth-java', environment: 'production', agentName: 'java' }) + .instance('instance-b'); await synthtraceEsClient.index( timerange(start, end) @@ -28,7 +30,7 @@ export async function generateData({ .generator((timestamp) => { return [ serviceRunsInContainerInstance - .transaction('GET /apple 🍎') + .transaction({ transactionName: 'GET /apple 🍎' }) .defaults({ 'container.id': 'foo', 'host.hostname': 'bar', @@ -38,7 +40,7 @@ export async function generateData({ .duration(1000) .success(), serviceInstance - .transaction('GET /banana 🍌') + .transaction({ transactionName: 'GET /banana 🍌' }) .defaults({ 'host.hostname': 'bar', }) diff --git a/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts b/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts index b38a7ef3052c2c..48ffb06ed3bf2f 100644 --- a/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts +++ b/x-pack/test/apm_api_integration/tests/latency/service_apis.spec.ts @@ -124,10 +124,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { const GO_DEV_DURATION = 500; before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceGoDevInstance = apm - .service(serviceName, 'development', 'go') + .service({ name: serviceName, environment: 'development', agentName: 'go' }) .instance('instance-b'); await synthtraceEsClient.index([ @@ -136,7 +136,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(GO_PROD_DURATION) .timestamp(timestamp) ), @@ -145,7 +145,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_DEV_RATE) .generator((timestamp) => serviceGoDevInstance - .transaction('GET /api/product/:id') + .transaction({ transactionName: 'GET /api/product/:id' }) .duration(GO_DEV_DURATION) .timestamp(timestamp) ), diff --git a/x-pack/test/apm_api_integration/tests/latency/service_maps.spec.ts b/x-pack/test/apm_api_integration/tests/latency/service_maps.spec.ts index e9b9749b659e21..5d1d3e6e62b54b 100644 --- a/x-pack/test/apm_api_integration/tests/latency/service_maps.spec.ts +++ b/x-pack/test/apm_api_integration/tests/latency/service_maps.spec.ts @@ -67,10 +67,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { const GO_DEV_DURATION = 500; before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceGoDevInstance = apm - .service(serviceName, 'development', 'go') + .service({ name: serviceName, environment: 'development', agentName: 'go' }) .instance('instance-b'); await synthtraceEsClient.index([ @@ -79,7 +79,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction('GET /api/product/list', 'Worker') + .transaction({ + transactionName: 'GET /api/product/list', + transactionType: 'Worker', + }) .duration(GO_PROD_DURATION) .timestamp(timestamp) ), @@ -88,7 +91,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_DEV_RATE) .generator((timestamp) => serviceGoDevInstance - .transaction('GET /api/product/:id') + .transaction({ transactionName: 'GET /api/product/:id' }) .duration(GO_DEV_DURATION) .timestamp(timestamp) ), diff --git a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts index d25b17cc0dc6b3..737efa4634de24 100644 --- a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts +++ b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.spec.ts @@ -90,14 +90,14 @@ export default function ApiTest({ getService }: FtrProviderContext) { const JAVA_PROD_RATE = 45; before(async () => { const serviceGoProdInstance = apm - .service('synth-go', 'production', 'go') + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceGoDevInstance = apm - .service('synth-go', 'development', 'go') + .service({ name: 'synth-go', environment: 'development', agentName: 'go' }) .instance('instance-b'); const serviceJavaInstance = apm - .service('synth-java', 'production', 'java') + .service({ name: 'synth-java', environment: 'production', agentName: 'java' }) .instance('instance-c'); await synthtraceEsClient.index([ @@ -106,7 +106,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .timestamp(timestamp) ), @@ -115,7 +115,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_DEV_RATE) .generator((timestamp) => serviceGoDevInstance - .transaction('GET /api/product/:id') + .transaction({ transactionName: 'GET /api/product/:id' }) .duration(1000) .timestamp(timestamp) ), @@ -124,7 +124,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(JAVA_PROD_RATE) .generator((timestamp) => serviceJavaInstance - .transaction('POST /api/product/buy') + .transaction({ transactionName: 'POST /api/product/buy' }) .duration(1000) .timestamp(timestamp) ), diff --git a/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts b/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts index c582c929c67cb4..5aeb0e7db72a4c 100644 --- a/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts +++ b/x-pack/test/apm_api_integration/tests/service_nodes/get_service_nodes.spec.ts @@ -50,7 +50,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { registry.when('Service nodes when data is loaded', { config: 'basic', archives: [] }, () => { before(async () => { - const instance = apm.service(serviceName, 'production', 'go').instance(instanceName); + const instance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance(instanceName); await synthtraceEsClient.index( timerange(start, end) .interval('1m') diff --git a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts index 8313ec635c69af..80865880cd6c40 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.spec.ts @@ -296,8 +296,16 @@ export default function ApiTest({ getService }: FtrProviderContext) { const rangeEnd = new Date('2021-01-01T12:15:00.000Z').getTime() - 1; before(async () => { - const goService = apm.service('opbeans-go', 'production', 'go'); - const javaService = apm.service('opbeans-java', 'production', 'java'); + const goService = apm.service({ + name: 'opbeans-go', + environment: 'production', + agentName: 'go', + }); + const javaService = apm.service({ + name: 'opbeans-java', + environment: 'production', + agentName: 'java', + }); const goInstanceA = goService.instance('go-instance-a'); const goInstanceB = goService.instance('go-instance-b'); @@ -310,7 +318,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { function withSpans(timestamp: number) { return new Array(3).fill(undefined).map(() => goInstanceA - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .timestamp(timestamp + 100) .duration(300) .destination('elasticsearch') @@ -321,7 +333,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { return synthtraceEsClient.index([ interval.rate(GO_A_INSTANCE_RATE_SUCCESS).generator((timestamp) => goInstanceA - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .success() .duration(500) .timestamp(timestamp) @@ -329,7 +341,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ), interval.rate(GO_A_INSTANCE_RATE_FAILURE).generator((timestamp) => goInstanceA - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .failure() .duration(500) .timestamp(timestamp) @@ -337,7 +349,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ), interval.rate(GO_B_INSTANCE_RATE_SUCCESS).generator((timestamp) => goInstanceB - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .success() .duration(500) .timestamp(timestamp) @@ -345,7 +357,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ), interval.rate(JAVA_INSTANCE_RATE).generator((timestamp) => javaInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .success() .duration(500) .timestamp(timestamp) diff --git a/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts b/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts index 2999b2f68c29eb..a93ac5420a785f 100644 --- a/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/services/error_groups/generate_data.ts @@ -27,7 +27,9 @@ export async function generateData({ start: number; end: number; }) { - const serviceGoProdInstance = apm.service(serviceName, 'production', 'go').instance('instance-a'); + const serviceGoProdInstance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance('instance-a'); const transactionNameProductList = 'GET /api/product/list'; const transactionNameProductId = 'GET /api/product/:id'; @@ -47,7 +49,7 @@ export async function generateData({ .rate(PROD_LIST_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductList) + .transaction({ transactionName: transactionNameProductList }) .timestamp(timestamp) .duration(1000) .success() @@ -57,8 +59,10 @@ export async function generateData({ .rate(PROD_LIST_ERROR_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductList) - .errors(serviceGoProdInstance.error(ERROR_NAME_1, 'foo').timestamp(timestamp)) + .transaction({ transactionName: transactionNameProductList }) + .errors( + serviceGoProdInstance.error({ message: ERROR_NAME_1, type: 'foo' }).timestamp(timestamp) + ) .duration(1000) .timestamp(timestamp) .failure() @@ -68,7 +72,7 @@ export async function generateData({ .rate(PROD_ID_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductId) + .transaction({ transactionName: transactionNameProductId }) .timestamp(timestamp) .duration(1000) .success() @@ -78,8 +82,10 @@ export async function generateData({ .rate(PROD_ID_ERROR_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionNameProductId) - .errors(serviceGoProdInstance.error(ERROR_NAME_2, 'bar').timestamp(timestamp)) + .transaction({ transactionName: transactionNameProductId }) + .errors( + serviceGoProdInstance.error({ message: ERROR_NAME_2, type: 'bar' }).timestamp(timestamp) + ) .duration(1000) .timestamp(timestamp) .failure() diff --git a/x-pack/test/apm_api_integration/tests/services/get_service_node_metadata.spec.ts b/x-pack/test/apm_api_integration/tests/services/get_service_node_metadata.spec.ts index 49160f9b5caf2d..faa160063dfa16 100644 --- a/x-pack/test/apm_api_integration/tests/services/get_service_node_metadata.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/get_service_node_metadata.spec.ts @@ -57,7 +57,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { { config: 'basic', archives: [] }, () => { before(async () => { - const instance = apm.service(serviceName, 'production', 'go').instance(instanceName); + const instance = apm + .service({ name: serviceName, environment: 'production', agentName: 'go' }) + .instance(instanceName); await synthtraceEsClient.index( timerange(start, end) .interval('1m') @@ -65,7 +67,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .generator((timestamp) => instance .containerId(instanceName) - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .timestamp(timestamp) .duration(1000) .success() diff --git a/x-pack/test/apm_api_integration/tests/services/service_details/generate_data.ts b/x-pack/test/apm_api_integration/tests/services/service_details/generate_data.ts index 4765f52b855d3a..22e8e12c668178 100644 --- a/x-pack/test/apm_api_integration/tests/services/service_details/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/services/service_details/generate_data.ts @@ -65,7 +65,9 @@ export async function generateData({ const { name: serviceRunTimeName, version: serviceRunTimeVersion } = runtime; const { name: agentName, version: agentVersion } = agent; - const instance = apm.service(serviceName, 'production', agentName).instance('instance-a'); + const instance = apm + .service({ name: serviceName, environment: 'production', agentName }) + .instance('instance-a'); const traceEvents = [ timerange(start, end) @@ -74,7 +76,7 @@ export async function generateData({ .generator((timestamp) => instance .containerId('instance-a') - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .timestamp(timestamp) .defaults({ 'cloud.provider': provider, @@ -101,7 +103,7 @@ export async function generateData({ .rate(rate) .generator((timestamp) => instance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .timestamp(timestamp) .defaults({ 'cloud.provider': provider, diff --git a/x-pack/test/apm_api_integration/tests/services/service_icons/generate_data.ts b/x-pack/test/apm_api_integration/tests/services/service_icons/generate_data.ts index 05f63f5ac05af5..36b0e30f92efd6 100644 --- a/x-pack/test/apm_api_integration/tests/services/service_icons/generate_data.ts +++ b/x-pack/test/apm_api_integration/tests/services/service_icons/generate_data.ts @@ -33,14 +33,16 @@ export async function generateData({ const { serviceName, agentName, rate, cloud, transaction } = dataConfig; const { provider, serviceName: cloudServiceName } = cloud; - const instance = apm.service(serviceName, 'production', agentName).instance('instance-a'); + const instance = apm + .service({ name: serviceName, environment: 'production', agentName }) + .instance('instance-a'); const traceEvents = timerange(start, end) .interval('30s') .rate(rate) .generator((timestamp) => instance - .transaction(transaction.name) + .transaction({ transactionName: transaction.name }) .defaults({ 'kubernetes.pod.uid': 'test', 'cloud.provider': provider, diff --git a/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts b/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts index ca2cb0c3d20a71..762722a77be79a 100644 --- a/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/sorted_and_filtered_services.spec.ts @@ -53,11 +53,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { // FLAKY: https://github.com/elastic/kibana/issues/127939 registry.when.skip('Sorted and filtered services', { config: 'trial', archives: [] }, () => { before(async () => { - const serviceA = apm.service(SERVICE_NAME_PREFIX + 'a', 'production', 'java').instance('a'); + const serviceA = apm + .service({ name: SERVICE_NAME_PREFIX + 'a', environment: 'production', agentName: 'java' }) + .instance('a'); - const serviceB = apm.service(SERVICE_NAME_PREFIX + 'b', 'development', 'go').instance('b'); + const serviceB = apm + .service({ name: SERVICE_NAME_PREFIX + 'b', environment: 'development', agentName: 'go' }) + .instance('b'); - const serviceC = apm.service(SERVICE_NAME_PREFIX + 'c', 'development', 'go').instance('c'); + const serviceC = apm + .service({ name: SERVICE_NAME_PREFIX + 'c', environment: 'development', agentName: 'go' }) + .instance('c'); const spikeStart = new Date('2021-01-07T12:00:00.000Z').getTime(); const spikeEnd = new Date('2021-01-07T14:00:00.000Z').getTime(); @@ -69,11 +75,11 @@ export default function ApiTest({ getService }: FtrProviderContext) { const isInSpike = spikeStart <= timestamp && spikeEnd >= timestamp; return [ serviceA - .transaction('GET /api') + .transaction({ transactionName: 'GET /api' }) .duration(isInSpike ? 1000 : 1100) .timestamp(timestamp), serviceB - .transaction('GET /api') + .transaction({ transactionName: 'GET /api' }) .duration(isInSpike ? 1000 : 4000) .timestamp(timestamp), ]; @@ -86,7 +92,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .interval('15m') .rate(1) .generator((timestamp) => { - return serviceC.transaction('GET /api', 'custom').duration(1000).timestamp(timestamp); + return serviceC + .transaction({ transactionName: 'GET /api', transactionType: 'custom' }) + .duration(1000) + .timestamp(timestamp); }); await synthtraceClient.index(eventsWithinTimerange.merge(eventsOutsideOfTimerange)); diff --git a/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts b/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts index c9c95b2e99bbc5..ffd6d43bec959a 100644 --- a/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/throughput.spec.ts @@ -71,14 +71,14 @@ export default function ApiTest({ getService }: FtrProviderContext) { before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceGoDevInstance = apm - .service(serviceName, 'development', 'go') + .service({ name: serviceName, environment: 'development', agentName: 'go' }) .instance('instance-b'); const serviceJavaInstance = apm - .service('synth-java', 'development', 'java') + .service({ name: 'synth-java', environment: 'development', agentName: 'java' }) .instance('instance-c'); await synthtraceEsClient.index([ @@ -87,7 +87,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .timestamp(timestamp) ), @@ -96,7 +96,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_DEV_RATE) .generator((timestamp) => serviceGoDevInstance - .transaction('GET /api/product/:id') + .transaction({ transactionName: 'GET /api/product/:id' }) .duration(1000) .timestamp(timestamp) ), @@ -105,7 +105,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(JAVA_PROD_RATE) .generator((timestamp) => serviceJavaInstance - .transaction('POST /api/product/buy') + .transaction({ transactionName: 'POST /api/product/buy' }) .duration(1000) .timestamp(timestamp) ), diff --git a/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts b/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts index 898f12ceaeffb2..c8b21729484bc3 100644 --- a/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/top_services.spec.ts @@ -71,19 +71,19 @@ export default function ApiTest({ getService }: FtrProviderContext) { const errorInterval = range.interval('5s'); const multipleEnvServiceProdInstance = apm - .service('multiple-env-service', 'production', 'go') + .service({ name: 'multiple-env-service', environment: 'production', agentName: 'go' }) .instance('multiple-env-service-production'); const multipleEnvServiceDevInstance = apm - .service('multiple-env-service', 'development', 'go') + .service({ name: 'multiple-env-service', environment: 'development', agentName: 'go' }) .instance('multiple-env-service-development'); const metricOnlyInstance = apm - .service('metric-only-service', 'production', 'java') + .service({ name: 'metric-only-service', environment: 'production', agentName: 'java' }) .instance('metric-only-production'); const errorOnlyInstance = apm - .service('error-only-service', 'production', 'java') + .service({ name: 'error-only-service', environment: 'production', agentName: 'java' }) .instance('error-only-production'); const config = { @@ -105,7 +105,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(config.multiple.prod.rps) .generator((timestamp) => multipleEnvServiceProdInstance - .transaction('GET /api') + .transaction({ transactionName: 'GET /api' }) .timestamp(timestamp) .duration(config.multiple.prod.duration) .success() @@ -114,7 +114,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(config.multiple.dev.rps) .generator((timestamp) => multipleEnvServiceDevInstance - .transaction('GET /api') + .transaction({ transactionName: 'GET /api' }) .timestamp(timestamp) .duration(config.multiple.dev.duration) .failure() @@ -123,7 +123,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(config.multiple.prod.rps) .generator((timestamp) => multipleEnvServiceDevInstance - .transaction('non-request', 'rpc') + .transaction({ transactionName: 'non-request', transactionType: 'rpc' }) .timestamp(timestamp) .duration(config.multiple.prod.duration) .success() @@ -140,7 +140,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { ), errorInterval .rate(1) - .generator((timestamp) => errorOnlyInstance.error('Foo').timestamp(timestamp)), + .generator((timestamp) => + errorOnlyInstance.error({ message: 'Foo' }).timestamp(timestamp) + ), ]); }); diff --git a/x-pack/test/apm_api_integration/tests/span_links/data_generator.ts b/x-pack/test/apm_api_integration/tests/span_links/data_generator.ts index 37bd72ff71c599..0af23ab0dc736b 100644 --- a/x-pack/test/apm_api_integration/tests/span_links/data_generator.ts +++ b/x-pack/test/apm_api_integration/tests/span_links/data_generator.ts @@ -10,7 +10,7 @@ import uuid from 'uuid'; function getProducerInternalOnly() { const producerInternalOnlyInstance = apm - .service('producer-internal-only', 'production', 'go') + .service({ name: 'producer-internal-only', environment: 'production', agentName: 'go' }) .instance('instance a'); const events = timerange( @@ -21,13 +21,13 @@ function getProducerInternalOnly() { .rate(1) .generator((timestamp) => { return producerInternalOnlyInstance - .transaction(`Transaction A`) + .transaction({ transactionName: `Transaction A` }) .timestamp(timestamp) .duration(1000) .success() .children( producerInternalOnlyInstance - .span(`Span A`, 'external', 'http') + .span({ spanName: `Span A`, spanType: 'external', spanSubtype: 'http' }) .timestamp(timestamp + 50) .duration(100) .success() @@ -57,7 +57,7 @@ function getProducerInternalOnly() { function getProducerExternalOnly() { const producerExternalOnlyInstance = apm - .service('producer-external-only', 'production', 'java') + .service({ name: 'producer-external-only', environment: 'production', agentName: 'java' }) .instance('instance b'); const events = timerange( @@ -68,13 +68,13 @@ function getProducerExternalOnly() { .rate(1) .generator((timestamp) => { return producerExternalOnlyInstance - .transaction(`Transaction B`) + .transaction({ transactionName: `Transaction B` }) .timestamp(timestamp) .duration(1000) .success() .children( producerExternalOnlyInstance - .span(`Span B`, 'external', 'http') + .span({ spanName: `Span B`, spanType: 'external', spanSubtype: 'http' }) .defaults({ 'span.links': [{ trace: { id: 'trace#1' }, span: { id: 'span#1' } }], }) @@ -82,7 +82,7 @@ function getProducerExternalOnly() { .duration(100) .success(), producerExternalOnlyInstance - .span(`Span B.1`, 'external', 'http') + .span({ spanName: `Span B.1`, spanType: 'external', spanSubtype: 'http' }) .timestamp(timestamp + 50) .duration(100) .success() @@ -130,7 +130,7 @@ function getProducerConsumer({ const externalTraceId = uuid.v4(); const producerConsumerInstance = apm - .service('producer-consumer', 'production', 'ruby') + .service({ name: 'producer-consumer', environment: 'production', agentName: 'ruby' }) .instance('instance c'); const events = timerange( @@ -141,7 +141,7 @@ function getProducerConsumer({ .rate(1) .generator((timestamp) => { return producerConsumerInstance - .transaction(`Transaction C`) + .transaction({ transactionName: `Transaction C` }) .defaults({ 'span.links': [ producerInternalOnlySpanASpanLink, @@ -154,7 +154,7 @@ function getProducerConsumer({ .success() .children( producerConsumerInstance - .span(`Span C`, 'external', 'http') + .span({ spanName: `Span C`, spanType: 'external', spanSubtype: 'http' }) .timestamp(timestamp + 50) .duration(100) .success() @@ -200,7 +200,7 @@ function getConsumerMultiple({ producerConsumerTransactionCLink: SpanLink; }) { const consumerMultipleInstance = apm - .service('consumer-multiple', 'production', 'nodejs') + .service({ name: 'consumer-multiple', environment: 'production', agentName: 'nodejs' }) .instance('instance d'); const events = timerange( @@ -211,14 +211,14 @@ function getConsumerMultiple({ .rate(1) .generator((timestamp) => { return consumerMultipleInstance - .transaction(`Transaction D`) + .transaction({ transactionName: `Transaction D` }) .defaults({ 'span.links': [producerInternalOnlySpanALink, producerConsumerSpanCLink] }) .timestamp(timestamp) .duration(1000) .success() .children( consumerMultipleInstance - .span(`Span E`, 'external', 'http') + .span({ spanName: `Span E`, spanType: 'external', spanSubtype: 'http' }) .defaults({ 'span.links': [producerExternalOnlySpanBLink, producerConsumerTransactionCLink], }) diff --git a/x-pack/test/apm_api_integration/tests/storage_explorer/storage_explorer_timeseries_chart.spec.ts b/x-pack/test/apm_api_integration/tests/storage_explorer/storage_explorer_timeseries_chart.spec.ts index fe0034c23e0bab..632e17c37509a5 100644 --- a/x-pack/test/apm_api_integration/tests/storage_explorer/storage_explorer_timeseries_chart.spec.ts +++ b/x-pack/test/apm_api_integration/tests/storage_explorer/storage_explorer_timeseries_chart.spec.ts @@ -56,21 +56,31 @@ export default function ApiTest({ getService }: FtrProviderContext) { let status: number; before(async () => { - const serviceGo1 = apm.service('synth-go-1', 'production', 'go').instance('instance'); - const serviceGo2 = apm.service('synth-go-2', 'production', 'go').instance('instance'); + const serviceGo1 = apm + .service({ name: 'synth-go-1', environment: 'production', agentName: 'go' }) + .instance('instance'); + const serviceGo2 = apm + .service({ name: 'synth-go-2', environment: 'production', agentName: 'go' }) + .instance('instance'); await synthtraceEsClient.index([ timerange(start, end) .interval('5m') .rate(1) .generator((timestamp) => - serviceGo1.transaction('GET /api/product/list1').duration(2000).timestamp(timestamp) + serviceGo1 + .transaction({ transactionName: 'GET /api/product/list1' }) + .duration(2000) + .timestamp(timestamp) ), timerange(start, end) .interval('5m') .rate(1) .generator((timestamp) => - serviceGo2.transaction('GET /api/product/list2').duration(2000).timestamp(timestamp) + serviceGo2 + .transaction({ transactionName: 'GET /api/product/list2' }) + .duration(2000) + .timestamp(timestamp) ), ]); diff --git a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts index c990a7c632caa9..926724156d553e 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.spec.ts @@ -99,10 +99,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { const JAVA_PROD_RATE = 25; before(async () => { const serviceGoProdInstance = apm - .service('synth-go', 'production', 'go') + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceJavaInstance = apm - .service('synth-java', 'development', 'java') + .service({ name: 'synth-java', environment: 'development', agentName: 'java' }) .instance('instance-c'); await synthtraceEsClient.index([ @@ -111,22 +111,30 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .timestamp(timestamp) .children( serviceGoProdInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .duration(1000) .success() .destination('elasticsearch') .timestamp(timestamp), serviceGoProdInstance - .span('custom_operation', 'app') + .span({ spanName: 'custom_operation', spanType: 'app' }) .duration(550) .children( serviceGoProdInstance - .span('SELECT FROM products', 'db', 'postgresql') + .span({ + spanName: 'SELECT FROM products', + spanType: 'db', + spanSubtype: 'postgresql', + }) .duration(500) .success() .destination('postgresql') @@ -141,18 +149,22 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(JAVA_PROD_RATE) .generator((timestamp) => serviceJavaInstance - .transaction('POST /api/product/buy') + .transaction({ transactionName: 'POST /api/product/buy' }) .duration(1000) .timestamp(timestamp) .children( serviceJavaInstance - .span('GET apm-*/_search', 'db', 'elasticsearch') + .span({ + spanName: 'GET apm-*/_search', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .duration(1000) .success() .destination('elasticsearch') .timestamp(timestamp), serviceJavaInstance - .span('custom_operation', 'app') + .span({ spanName: 'custom_operation', spanType: 'app' }) .duration(50) .success() .timestamp(timestamp) diff --git a/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts b/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts index ef091dc83a429e..d4d843e8cc6639 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/service_apis.spec.ts @@ -110,10 +110,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { const GO_DEV_RATE = 20; before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceGoDevInstance = apm - .service(serviceName, 'development', 'go') + .service({ name: serviceName, environment: 'development', agentName: 'go' }) .instance('instance-b'); await synthtraceEsClient.index([ @@ -122,7 +122,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction('GET /api/product/list') + .transaction({ transactionName: 'GET /api/product/list' }) .duration(1000) .timestamp(timestamp) ), @@ -131,7 +131,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_DEV_RATE) .generator((timestamp) => serviceGoDevInstance - .transaction('GET /api/product/:id') + .transaction({ transactionName: 'GET /api/product/:id' }) .duration(1000) .timestamp(timestamp) ), diff --git a/x-pack/test/apm_api_integration/tests/throughput/service_maps.spec.ts b/x-pack/test/apm_api_integration/tests/throughput/service_maps.spec.ts index fd775ec9af2a9e..039a4f0f548b02 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/service_maps.spec.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/service_maps.spec.ts @@ -75,10 +75,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { const GO_DEV_RATE = 20; before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const serviceGoDevInstance = apm - .service(serviceName, 'development', 'go') + .service({ name: serviceName, environment: 'development', agentName: 'go' }) .instance('instance-b'); await synthtraceEsClient.index([ @@ -87,7 +87,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction('GET /apple 🍎 ', 'Worker') + .transaction({ transactionName: 'GET /apple 🍎 ', transactionType: 'Worker' }) .duration(1000) .timestamp(timestamp) ), @@ -95,7 +95,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { .interval('1m') .rate(GO_DEV_RATE) .generator((timestamp) => - serviceGoDevInstance.transaction('GET /apple 🍎 ').duration(1000).timestamp(timestamp) + serviceGoDevInstance + .transaction({ transactionName: 'GET /apple 🍎 ' }) + .duration(1000) + .timestamp(timestamp) ), ]); }); diff --git a/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts b/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts index 0c0696f801a952..a2a44e7d086da1 100644 --- a/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts +++ b/x-pack/test/apm_api_integration/tests/traces/find_traces.spec.ts @@ -97,11 +97,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { registry.when('Find traces when traces exist', { config: 'basic', archives: [] }, () => { before(() => { - const java = apm.service('java', 'production', 'java').instance('java'); + const java = apm + .service({ name: 'java', environment: 'production', agentName: 'java' }) + .instance('java'); - const node = apm.service('node', 'development', 'nodejs').instance('node'); + const node = apm + .service({ name: 'node', environment: 'development', agentName: 'nodejs' }) + .instance('node'); - const python = apm.service('python', 'production', 'python').instance('python'); + const python = apm + .service({ name: 'python', environment: 'production', agentName: 'python' }) + .instance('python'); function generateTrace(timestamp: number, order: Instance[], db?: 'elasticsearch' | 'redis') { return order @@ -114,7 +120,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const time = timestamp + invertedIndex * 10; const transaction: Transaction = instance - .transaction(`GET /${instance.fields['service.name']!}/api`) + .transaction({ transactionName: `GET /${instance.fields['service.name']!}/api` }) .timestamp(time) .duration(duration); @@ -122,7 +128,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const next = order[invertedIndex + 1].fields['service.name']!; transaction.children( instance - .span(`GET ${next}/api`, 'external', 'http') + .span({ spanName: `GET ${next}/api`, spanType: 'external', spanSubtype: 'http' }) .destination(next) .duration(duration) .timestamp(time + 1) @@ -131,7 +137,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { } else if (db) { transaction.children( instance - .span(db, 'db', db) + .span({ spanName: db, spanType: 'db', spanSubtype: db }) .destination(db) .duration(duration) .timestamp(time + 1) diff --git a/x-pack/test/apm_api_integration/tests/traces/trace_by_id.spec.ts b/x-pack/test/apm_api_integration/tests/traces/trace_by_id.spec.ts index 509d70caf52916..087ec58e83806a 100644 --- a/x-pack/test/apm_api_integration/tests/traces/trace_by_id.spec.ts +++ b/x-pack/test/apm_api_integration/tests/traces/trace_by_id.spec.ts @@ -55,25 +55,31 @@ export default function ApiTest({ getService }: FtrProviderContext) { registry.when('Trace exists', { config: 'basic', archives: [] }, () => { let serviceATraceId: string; before(async () => { - const instanceJava = apm.service('synth-apple', 'production', 'java').instance('instance-b'); + const instanceJava = apm + .service({ name: 'synth-apple', environment: 'production', agentName: 'java' }) + .instance('instance-b'); const events = timerange(start, end) .interval('1m') .rate(1) .generator((timestamp) => { return [ instanceJava - .transaction('GET /apple 🍏') + .transaction({ transactionName: 'GET /apple 🍏' }) .timestamp(timestamp) .duration(1000) .failure() .errors( instanceJava - .error('[ResponseError] index_not_found_exception') + .error({ message: '[ResponseError] index_not_found_exception' }) .timestamp(timestamp + 50) ) .children( instanceJava - .span('get_green_apple_🍏', 'db', 'elasticsearch') + .span({ + spanName: 'get_green_apple_🍏', + spanType: 'db', + spanSubtype: 'elasticsearch', + }) .timestamp(timestamp + 50) .duration(900) .success() diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts index 350830abcbba3a..7215dd933c87e8 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts @@ -81,7 +81,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const GO_PROD_ERROR_RATE = 25; before(async () => { const serviceGoProdInstance = apm - .service(serviceName, 'production', 'go') + .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); const transactionName = 'GET /api/product/list'; @@ -92,7 +92,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionName) + .transaction({ transactionName }) .timestamp(timestamp) .duration(1000) .success() @@ -102,7 +102,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .rate(GO_PROD_ERROR_RATE) .generator((timestamp) => serviceGoProdInstance - .transaction(transactionName) + .transaction({ transactionName }) .duration(1000) .timestamp(timestamp) .failure() From 1d1f060071a8f3cda8148a98af8027d4c27c7c42 Mon Sep 17 00:00:00 2001 From: Baturalp Gurdin <9674241+suchcodemuchwow@users.noreply.github.com> Date: Tue, 13 Sep 2022 16:47:25 +0300 Subject: [PATCH 114/144] skip flaky jest suite (#140620) --- .../components/artifact_list_page/artifact_list_page.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx index 86ec7431bd8011..9160732e32b3eb 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_list_page/artifact_list_page.test.tsx @@ -16,7 +16,8 @@ import { getDeferred } from '../mocks'; jest.mock('../../../common/components/user_privileges'); -describe('When using the ArtifactListPage component', () => { +// FLAKY: https://github.com/elastic/kibana/issues/140620 +describe.skip('When using the ArtifactListPage component', () => { let render: ( props?: Partial<ArtifactListPageProps> ) => ReturnType<AppContextTestRender['render']>; From a30356314f7c4d6fe0ae13c24c78050271abc91a Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <xavier.mouligneau@elastic.co> Date: Tue, 13 Sep 2022 09:59:18 -0400 Subject: [PATCH 115/144] fix loading cell between pagination (#140440) Co-authored-by: Maryam Saeidi <maryam.saeidi@elastic.co> --- .../sections/alerts_table/alerts_table.tsx | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx index f8092475f1ba0b..302392674ccddf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx @@ -15,6 +15,7 @@ import { EuiToolTip, EuiButtonIcon, EuiDataGridStyle, + EuiLoadingContent, } from '@elastic/eui'; import { useSorting, usePagination, useBulkActions } from './hooks'; import { AlertsTableProps } from '../../../types'; @@ -219,16 +220,21 @@ const AlertsTable: React.FunctionComponent<AlertsTableProps> = (props: AlertsTab (_props: EuiDataGridCellValueElementProps) => { // https://github.com/elastic/eui/issues/5811 const alert = alerts[_props.rowIndex - pagination.pageSize * pagination.pageIndex]; - const data: Array<{ field: string; value: string[] }> = []; - Object.entries(alert ?? {}).forEach(([key, value]) => { - data.push({ field: key, value: value as string[] }); - }); - return renderCellValue({ - ..._props, - data, - }); + if (alert) { + const data: Array<{ field: string; value: string[] }> = []; + Object.entries(alert ?? {}).forEach(([key, value]) => { + data.push({ field: key, value: value as string[] }); + }); + return renderCellValue({ + ..._props, + data, + }); + } else if (isLoading) { + return <EuiLoadingContent lines={1} />; + } + return null; }, - [alerts, pagination.pageIndex, pagination.pageSize, renderCellValue] + [alerts, isLoading, pagination.pageIndex, pagination.pageSize, renderCellValue] ); return ( From 926badd112169cf870a8251cfa02c789dafbb785 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Tue, 13 Sep 2022 16:11:06 +0200 Subject: [PATCH 116/144] [Security Solution][Endpoint][Response Actions] Persist actions log filter values via url params on Action History page (#140474) * persist actions log filter values via url params fixes elastic/security-team/issues/4742 * move URL param hook to response actions components fixes elastic/security-team/issues/4742 * add more tests fixes elastic/security-team/issues/4742 * update tests * verify commands and statuses are not undefined review changes (@paul-tavares) --- .../actions_log_date_range_picker.tsx | 16 +- .../components/actions_log_filter.tsx | 68 +++- .../components/actions_log_filters.tsx | 12 +- .../components/hooks.tsx | 91 ++++- .../use_action_history_url_params.test.ts | 109 ++++++ .../use_action_history_url_params.ts | 194 +++++++++++ .../endpoint_response_actions_list/mocks.tsx | 75 +++++ .../response_actions_log.test.tsx | 95 ++---- .../response_actions_log.tsx | 94 ++++-- .../view/response_actions_list_page.test.tsx | 316 ++++++++++++++++++ .../view/response_actions_list_page.tsx | 2 +- 11 files changed, 954 insertions(+), 118 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts create mode 100644 x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/mocks.tsx create mode 100644 x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx index 015fd3a501621a..385449d8754b61 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx @@ -18,6 +18,7 @@ import type { import { UI_SETTINGS } from '@kbn/data-plugin/common'; import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; +import { useActionHistoryUrlParams } from './use_action_history_url_params'; export interface DateRangePickerValues { autoRefreshOptions: { @@ -37,16 +38,19 @@ export const ActionLogDateRangePicker = memo( ({ dateRangePickerState, isDataLoading, + isFlyout, onRefresh, onRefreshChange, onTimeChange, }: { dateRangePickerState: DateRangePickerValues; isDataLoading: boolean; + isFlyout: boolean; onRefresh: () => void; onRefreshChange: (evt: OnRefreshChangeProps) => void; onTimeChange: ({ start, end }: DurationRange) => void; }) => { + const { startDate: startDateFromUrl, endDate: endDateFromUrl } = useActionHistoryUrlParams(); const getTestId = useTestIdGenerator('response-actions-list'); const kibana = useKibana<IDataPluginServices>(); const { uiSettings } = kibana.services; @@ -72,14 +76,22 @@ export const ActionLogDateRangePicker = memo( isLoading={isDataLoading} dateFormat={uiSettings.get('dateFormat')} commonlyUsedRanges={commonlyUsedRanges} - end={dateRangePickerState.endDate} + end={ + isFlyout + ? dateRangePickerState.endDate + : endDateFromUrl ?? dateRangePickerState.endDate + } isPaused={!dateRangePickerState.autoRefreshOptions.enabled} onTimeChange={onTimeChange} onRefreshChange={onRefreshChange} refreshInterval={dateRangePickerState.autoRefreshOptions.duration} onRefresh={onRefresh} recentlyUsedRanges={dateRangePickerState.recentlyUsedDateRanges} - start={dateRangePickerState.startDate} + start={ + isFlyout + ? dateRangePickerState.startDate + : startDateFromUrl ?? dateRangePickerState.startDate + } showUpdateButton={false} updateButtonProps={{ iconOnly: true, fill: false }} width="auto" diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx index 9a5903a278fb7d..e26f1375984b59 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx @@ -7,8 +7,9 @@ import React, { memo, useMemo, useCallback } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSelectable, EuiPopoverTitle } from '@elastic/eui'; +import type { ResponseActions } from '../../../../../common/endpoint/service/response_actions/constants'; import { ActionsLogFilterPopover } from './actions_log_filter_popover'; -import { type FilterItems, type FilterName, useActionsLogFilter } from './hooks'; +import { type FilterItems, type FilterName, useActionsLogFilter, getUiCommand } from './hooks'; import { ClearAllButton } from './clear_all_button'; import { UX_MESSAGES } from '../translations'; import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; @@ -16,22 +17,32 @@ import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; export const ActionsLogFilter = memo( ({ filterName, + isFlyout, onChangeFilterOptions, }: { filterName: FilterName; + isFlyout: boolean; onChangeFilterOptions: (selectedOptions: string[]) => void; }) => { const getTestId = useTestIdGenerator('response-actions-list'); - const { items, setItems, hasActiveFilters, numActiveFilters, numFilters } = - useActionsLogFilter(filterName); + const { + items, + setItems, + hasActiveFilters, + numActiveFilters, + numFilters, + setUrlActionsFilters, + setUrlStatusesFilters, + } = useActionsLogFilter(filterName, isFlyout); const isSearchable = useMemo(() => filterName !== 'statuses', [filterName]); const onChange = useCallback( (newOptions: FilterItems) => { - setItems(newOptions.map((e) => e)); + // update filter UI options state + setItems(newOptions.map((option) => option)); - // update selected filter state + // compute selected list of options const selectedItems = newOptions.reduce<string[]>((acc, curr) => { if (curr.checked === 'on') { acc.push(curr.key); @@ -39,22 +50,59 @@ export const ActionsLogFilter = memo( return acc; }, []); + if (!isFlyout) { + // update URL params + if (filterName === 'actions') { + setUrlActionsFilters( + selectedItems.map((item) => getUiCommand(item as ResponseActions)).join() + ); + } else if (filterName === 'statuses') { + setUrlStatusesFilters(selectedItems.join()); + } + } + // update query state onChangeFilterOptions(selectedItems); }, - [setItems, onChangeFilterOptions] + [ + filterName, + isFlyout, + setItems, + onChangeFilterOptions, + setUrlActionsFilters, + setUrlStatusesFilters, + ] ); // clear all selected options const onClearAll = useCallback(() => { + // update filter UI options state setItems( - items.map((e) => { - e.checked = undefined; - return e; + items.map((option) => { + option.checked = undefined; + return option; }) ); + + if (!isFlyout) { + // update URL params + if (filterName === 'actions') { + setUrlActionsFilters(''); + } else if (filterName === 'statuses') { + setUrlStatusesFilters(''); + } + } + // update query state onChangeFilterOptions([]); - }, [items, setItems, onChangeFilterOptions]); + }, [ + filterName, + isFlyout, + items, + setItems, + onChangeFilterOptions, + setUrlActionsFilters, + setUrlStatusesFilters, + ]); return ( <ActionsLogFilterPopover diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx index 8512cc50dad296..9b65a2b33f752d 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx @@ -22,6 +22,7 @@ export const ActionsLogFilters = memo( ({ dateRangePickerState, isDataLoading, + isFlyout, onClick, onChangeCommandsFilter, onChangeStatusesFilter, @@ -31,6 +32,7 @@ export const ActionsLogFilters = memo( }: { dateRangePickerState: DateRangePickerValues; isDataLoading: boolean; + isFlyout: boolean; onChangeCommandsFilter: (selectedCommands: string[]) => void; onChangeStatusesFilter: (selectedStatuses: string[]) => void; onRefresh: () => void; @@ -43,14 +45,19 @@ export const ActionsLogFilters = memo( // TODO: add more filter names here (users, hosts, statuses) return ( <> - <ActionsLogFilter filterName={'actions'} onChangeFilterOptions={onChangeCommandsFilter} /> + <ActionsLogFilter + filterName={'actions'} + isFlyout={isFlyout} + onChangeFilterOptions={onChangeCommandsFilter} + /> <ActionsLogFilter filterName={'statuses'} + isFlyout={isFlyout} onChangeFilterOptions={onChangeStatusesFilter} /> </> ); - }, [onChangeCommandsFilter, onChangeStatusesFilter]); + }, [isFlyout, onChangeCommandsFilter, onChangeStatusesFilter]); const onClickRefreshButton = useCallback(() => onClick(), [onClick]); @@ -63,6 +70,7 @@ export const ActionsLogFilters = memo( <ActionLogDateRangePicker dateRangePickerState={dateRangePickerState} isDataLoading={isDataLoading} + isFlyout={isFlyout} onRefresh={onRefresh} onRefreshChange={onRefreshChange} onTimeChange={onTimeChange} diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx index 323c46a6cbbdaa..4552d3912f8421 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/hooks.tsx @@ -22,6 +22,7 @@ import type { DateRangePickerValues } from './actions_log_date_range_picker'; import type { FILTER_NAMES } from '../translations'; import { UX_MESSAGES } from '../translations'; import { StatusBadge } from './status_badge'; +import { useActionHistoryUrlParams } from './use_action_history_url_params'; const defaultDateRangeOptions = Object.freeze({ autoRefreshOptions: { @@ -33,7 +34,8 @@ const defaultDateRangeOptions = Object.freeze({ recentlyUsedDateRanges: [], }); -export const useDateRangePicker = () => { +export const useDateRangePicker = (isFlyout: boolean) => { + const { setUrlDateRangeFilters } = useActionHistoryUrlParams(); const [dateRangePickerState, setDateRangePickerState] = useState<DateRangePickerValues>(defaultDateRangeOptions); @@ -86,9 +88,16 @@ export const useDateRangePicker = () => { .slice(0, 9), ]; updateActionListRecentlyUsedDateRanges(newRecentlyUsedDateRanges); + + // update URL params for date filters + if (!isFlyout) { + setUrlDateRangeFilters({ startDate: newStart, endDate: newEnd }); + } }, [ dateRangePickerState.recentlyUsedDateRanges, + isFlyout, + setUrlDateRangeFilters, updateActionListDateRanges, updateActionListRecentlyUsedDateRanges, ] @@ -101,6 +110,7 @@ export type FilterItems = Array<{ key: string; label: string; checked: 'on' | undefined; + 'data-test-subj': string; }>; export const getActionStatus = (status: ResponseActionStatus): string => { @@ -114,41 +124,84 @@ export const getActionStatus = (status: ResponseActionStatus): string => { return ''; }; -export const getCommand = ( +/** + * map actual command to ui command + * unisolate -> release + * running-processes -> processes + */ +export const getUiCommand = ( command: ResponseActions -): Exclude<ResponseActions, 'unisolate' | 'running-processes'> | 'release' | 'processes' => - command === 'unisolate' ? 'release' : command === 'running-processes' ? 'processes' : command; +): Exclude<ResponseActions, 'unisolate' | 'running-processes'> | 'release' | 'processes' => { + if (command === 'unisolate') { + return 'release'; + } else if (command === 'running-processes') { + return 'processes'; + } else { + return command; + } +}; + +/** + * map UI command back to actual command + * release -> unisolate + * processes -> running-processes + */ +export const getCommandKey = ( + uiCommand: Exclude<ResponseActions, 'unisolate' | 'running-processes'> | 'release' | 'processes' +): ResponseActions => { + if (uiCommand === 'release') { + return 'unisolate'; + } else if (uiCommand === 'processes') { + return 'running-processes'; + } else { + return uiCommand; + } +}; // TODO: add more filter names here export type FilterName = keyof typeof FILTER_NAMES; export const useActionsLogFilter = ( - filterName: FilterName + filterName: FilterName, + isFlyout: boolean ): { items: FilterItems; setItems: React.Dispatch<React.SetStateAction<FilterItems>>; hasActiveFilters: boolean; numActiveFilters: number; numFilters: number; + setUrlActionsFilters: ReturnType<typeof useActionHistoryUrlParams>['setUrlActionsFilters']; + setUrlStatusesFilters: ReturnType<typeof useActionHistoryUrlParams>['setUrlStatusesFilters']; } => { + const { commands, statuses, setUrlActionsFilters, setUrlStatusesFilters } = + useActionHistoryUrlParams(); const isStatusesFilter = filterName === 'statuses'; const [items, setItems] = useState<FilterItems>( isStatusesFilter - ? RESPONSE_ACTION_STATUS.map((filter) => ({ - key: filter, + ? RESPONSE_ACTION_STATUS.map((statusName) => ({ + key: statusName, label: ( <StatusBadge color={ - filter === 'successful' ? 'success' : filter === 'failed' ? 'danger' : 'warning' + statusName === 'successful' + ? 'success' + : statusName === 'failed' + ? 'danger' + : 'warning' } - status={getActionStatus(filter)} + status={getActionStatus(statusName)} /> ) as unknown as string, - checked: undefined, + checked: !isFlyout && statuses?.includes(statusName) ? 'on' : undefined, + 'data-test-subj': `${filterName}-filter-option`, })) - : RESPONSE_ACTION_COMMANDS.map((filter) => ({ - key: filter, - label: getCommand(filter), - checked: undefined, + : RESPONSE_ACTION_COMMANDS.map((commandName) => ({ + key: commandName, + label: getUiCommand(commandName), + checked: + !isFlyout && commands?.map((command) => getCommandKey(command)).includes(commandName) + ? 'on' + : undefined, + 'data-test-subj': `${filterName}-filter-option`, })) ); @@ -159,5 +212,13 @@ export const useActionsLogFilter = ( ); const numFilters = useMemo(() => items.filter((item) => item.checked !== 'on').length, [items]); - return { items, setItems, hasActiveFilters, numActiveFilters, numFilters }; + return { + items, + setItems, + hasActiveFilters, + numActiveFilters, + numFilters, + setUrlActionsFilters, + setUrlStatusesFilters, + }; }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts new file mode 100644 index 00000000000000..376adee67bb360 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.test.ts @@ -0,0 +1,109 @@ +/* + * 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 { actionsLogFiltersFromUrlParams } from './use_action_history_url_params'; + +describe('#actionsLogFiltersFromUrlParams', () => { + it('should not use invalid command values to URL params', () => { + expect(actionsLogFiltersFromUrlParams({ commands: 'asa,was' })).toEqual({ + commands: undefined, + endDate: undefined, + hosts: undefined, + startDate: undefined, + statuses: undefined, + users: undefined, + }); + }); + + it('should use valid command values to URL params', () => { + expect( + actionsLogFiltersFromUrlParams({ + commands: 'kill-process,isolate,processes,release,suspend-process', + }) + ).toEqual({ + commands: ['isolate', 'kill-process', 'processes', 'release', 'suspend-process'], + endDate: undefined, + hosts: undefined, + startDate: undefined, + statuses: undefined, + users: undefined, + }); + }); + + it('should not use invalid status values to URL params', () => { + expect(actionsLogFiltersFromUrlParams({ statuses: 'asa,was' })).toEqual({ + commands: undefined, + endDate: undefined, + hosts: undefined, + startDate: undefined, + statuses: undefined, + users: undefined, + }); + }); + + it('should use valid status values to URL params', () => { + expect( + actionsLogFiltersFromUrlParams({ + statuses: 'successful,pending,failed', + }) + ).toEqual({ + commands: undefined, + endDate: undefined, + hosts: undefined, + startDate: undefined, + statuses: ['failed', 'pending', 'successful'], + users: undefined, + }); + }); + + it('should use valid command and status values to URL params', () => { + expect( + actionsLogFiltersFromUrlParams({ + commands: 'release,kill-process,isolate,processes,suspend-process', + statuses: 'successful,pending,failed', + }) + ).toEqual({ + commands: ['isolate', 'kill-process', 'processes', 'release', 'suspend-process'], + endDate: undefined, + hosts: undefined, + startDate: undefined, + statuses: ['failed', 'pending', 'successful'], + users: undefined, + }); + }); + + it('should use set given relative startDate and endDate values to URL params', () => { + expect( + actionsLogFiltersFromUrlParams({ + startDate: 'now-24h/h', + endDate: 'now', + }) + ).toEqual({ + commands: undefined, + endDate: 'now', + hosts: undefined, + startDate: 'now-24h/h', + statuses: undefined, + users: undefined, + }); + }); + + it('should use set given absolute startDate and endDate values to URL params', () => { + expect( + actionsLogFiltersFromUrlParams({ + startDate: '2022-09-12T08:00:00.000Z', + endDate: '2022-09-12T08:30:33.140Z', + }) + ).toEqual({ + commands: undefined, + endDate: '2022-09-12T08:30:33.140Z', + hosts: undefined, + startDate: '2022-09-12T08:00:00.000Z', + statuses: undefined, + users: undefined, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts new file mode 100644 index 00000000000000..24d728bd5c1893 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts @@ -0,0 +1,194 @@ +/* + * 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 { useCallback, useEffect, useMemo, useState } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; +import { + RESPONSE_ACTION_COMMANDS, + RESPONSE_ACTION_STATUS, + type ResponseActions, + type ResponseActionStatus, +} from '../../../../../common/endpoint/service/response_actions/constants'; +import { useUrlParams } from '../../../hooks/use_url_params'; + +interface UrlParamsActionsLogFilters { + commands: string; + hosts: string; + statuses: string; + startDate: string; + endDate: string; + users: string; +} + +interface ActionsLogFiltersFromUrlParams { + commands?: Array< + Exclude<ResponseActions, 'unisolate' | 'running-processes'> | 'release' | 'processes' + >; + hosts?: string[]; + statuses?: ResponseActionStatus[]; + startDate?: string; + endDate?: string; + setUrlActionsFilters: (commands: UrlParamsActionsLogFilters['commands']) => void; + setUrlDateRangeFilters: ({ startDate, endDate }: { startDate: string; endDate: string }) => void; + setUrlHostsFilters: (agentIds: UrlParamsActionsLogFilters['hosts']) => void; + setUrlStatusesFilters: (statuses: UrlParamsActionsLogFilters['statuses']) => void; + setUrlUsersFilters: (users: UrlParamsActionsLogFilters['users']) => void; + users?: string[]; +} + +type FiltersFromUrl = Pick< + ActionsLogFiltersFromUrlParams, + 'commands' | 'hosts' | 'statuses' | 'users' | 'startDate' | 'endDate' +>; + +export const actionsLogFiltersFromUrlParams = ( + urlParams: Partial<UrlParamsActionsLogFilters> +): FiltersFromUrl => { + const actionsLogFilters: FiltersFromUrl = { + commands: [], + hosts: [], + statuses: [], + startDate: 'now-24h/h', + endDate: 'now', + users: [], + }; + + const urlCommands = urlParams.commands + ? String(urlParams.commands) + .split(',') + .reduce<Required<ActionsLogFiltersFromUrlParams>['commands']>((acc, curr) => { + if ( + RESPONSE_ACTION_COMMANDS.includes(curr as ResponseActions) || + curr === 'release' || + curr === 'processes' + ) { + acc.push(curr as Required<ActionsLogFiltersFromUrlParams>['commands'][number]); + } + return acc.sort(); + }, []) + : []; + + const urlHosts = urlParams.hosts ? String(urlParams.hosts).split(',').sort() : []; + + const urlStatuses = urlParams.statuses + ? (String(urlParams.statuses).split(',') as ResponseActionStatus[]).reduce< + ResponseActionStatus[] + >((acc, curr) => { + if (RESPONSE_ACTION_STATUS.includes(curr)) { + acc.push(curr); + } + return acc.sort(); + }, []) + : []; + + const urlUsers = urlParams.hosts ? String(urlParams.users).split(',').sort() : []; + + actionsLogFilters.commands = urlCommands.length ? urlCommands : undefined; + actionsLogFilters.hosts = urlHosts.length ? urlHosts : undefined; + actionsLogFilters.statuses = urlStatuses.length ? urlStatuses : undefined; + actionsLogFilters.startDate = urlParams.startDate ? String(urlParams.startDate) : undefined; + actionsLogFilters.endDate = urlParams.endDate ? String(urlParams.endDate) : undefined; + actionsLogFilters.users = urlUsers.length ? urlUsers : undefined; + + return actionsLogFilters; +}; + +export const useActionHistoryUrlParams = (): ActionsLogFiltersFromUrlParams => { + // track actions and status filters + const location = useLocation(); + const history = useHistory(); + const { urlParams, toUrlParams } = useUrlParams(); + + const getUrlActionsLogFilters = useMemo( + () => actionsLogFiltersFromUrlParams(urlParams), + [urlParams] + ); + const [actionsLogFilters, setActionsLogFilters] = useState(getUrlActionsLogFilters); + + const setUrlActionsFilters = useCallback( + (commands: string) => { + history.push({ + ...location, + search: toUrlParams({ + ...urlParams, + commands: commands.length ? commands : undefined, + }), + }); + }, + [history, location, toUrlParams, urlParams] + ); + + const setUrlHostsFilters = useCallback( + (agentIds: string) => { + history.push({ + ...location, + search: toUrlParams({ + ...urlParams, + hosts: agentIds.length ? agentIds : undefined, + }), + }); + }, + [history, location, toUrlParams, urlParams] + ); + + const setUrlStatusesFilters = useCallback( + (statuses: string) => { + history.push({ + ...location, + search: toUrlParams({ + ...urlParams, + statuses: statuses.length ? statuses : undefined, + }), + }); + }, + [history, location, toUrlParams, urlParams] + ); + + const setUrlUsersFilters = useCallback( + (users: string) => { + history.push({ + ...location, + search: toUrlParams({ + ...urlParams, + users: users.length ? users : undefined, + }), + }); + }, + [history, location, toUrlParams, urlParams] + ); + + const setUrlDateRangeFilters = useCallback( + ({ startDate, endDate }: { startDate: string; endDate: string }) => { + history.push({ + ...location, + search: toUrlParams({ + ...urlParams, + startDate: startDate.length ? startDate : undefined, + endDate: endDate.length ? endDate : undefined, + }), + }); + }, + [history, location, toUrlParams, urlParams] + ); + + useEffect(() => { + setActionsLogFilters((prevState) => { + return { + ...prevState, + ...actionsLogFiltersFromUrlParams(urlParams), + }; + }); + }, [setActionsLogFilters, urlParams]); + + return { + ...actionsLogFilters, + setUrlActionsFilters, + setUrlDateRangeFilters, + setUrlHostsFilters, + setUrlStatusesFilters, + setUrlUsersFilters, + }; +}; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/mocks.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/mocks.tsx new file mode 100644 index 00000000000000..65b40d9a924ea1 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/mocks.tsx @@ -0,0 +1,75 @@ +/* + * 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 uuid from 'uuid'; +import type { ActionListApiResponse } from '../../../../common/endpoint/types'; +import type { ResponseActionStatus } from '../../../../common/endpoint/service/response_actions/constants'; +import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; + +export const getActionListMock = async ({ + agentIds: _agentIds, + commands, + actionCount = 0, + endDate, + page = 1, + pageSize = 10, + startDate, + userIds, + isCompleted = true, + isExpired = false, + wasSuccessful = true, + status = 'successful', +}: { + agentIds?: string[]; + commands?: string[]; + actionCount?: number; + endDate?: string; + page?: number; + pageSize?: number; + startDate?: string; + userIds?: string[]; + isCompleted?: boolean; + isExpired?: boolean; + wasSuccessful?: boolean; + status?: ResponseActionStatus; +}): Promise<ActionListApiResponse> => { + const endpointActionGenerator = new EndpointActionGenerator('seed'); + + const agentIds = _agentIds ?? [uuid.v4()]; + + const data: ActionListApiResponse['data'] = agentIds.map((id) => { + const actionIds = Array(actionCount) + .fill(1) + .map(() => uuid.v4()); + + const actionDetails: ActionListApiResponse['data'] = actionIds.map((actionId) => { + return endpointActionGenerator.generateActionDetails({ + agents: [id], + id: actionId, + isCompleted, + isExpired, + wasSuccessful, + status, + completedAt: isExpired ? undefined : new Date().toISOString(), + }); + }); + return actionDetails; + })[0]; + + return { + page, + pageSize, + startDate, + endDate, + elasticAgentIds: agentIds, + commands, + data, + userIds, + statuses: undefined, + total: data.length ?? 0, + }; +}; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx index 1f5e39c532a6f4..64910663ac5cf1 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx @@ -5,18 +5,18 @@ * 2.0. */ -import uuid from 'uuid'; import React from 'react'; import * as reactTestingLibrary from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; -import type { AppContextTestRender } from '../../../common/mock/endpoint'; -import { createAppRootMockRenderer } from '../../../common/mock/endpoint'; +import { + createAppRootMockRenderer, + type AppContextTestRender, +} from '../../../common/mock/endpoint'; import { ResponseActionsLog } from './response_actions_log'; import type { ActionListApiResponse } from '../../../../common/endpoint/types'; -import type { ResponseActionStatus } from '../../../../common/endpoint/service/response_actions/constants'; import { MANAGEMENT_PATH } from '../../../../common/constants'; -import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; +import { getActionListMock } from './mocks'; let mockUseGetEndpointActionList: { isFetched?: boolean; @@ -500,69 +500,28 @@ describe('Response Actions Log', () => { expect(clearAllButton.hasAttribute('disabled')).toBeTruthy(); }); }); -}); -// mock API response -const getActionListMock = async ({ - agentIds: _agentIds, - commands, - actionCount = 0, - endDate, - page = 1, - pageSize = 10, - startDate, - userIds, - isCompleted = true, - isExpired = false, - wasSuccessful = true, - status = 'successful', -}: { - agentIds?: string[]; - commands?: string[]; - actionCount?: number; - endDate?: string; - page?: number; - pageSize?: number; - startDate?: string; - userIds?: string[]; - isCompleted?: boolean; - isExpired?: boolean; - wasSuccessful?: boolean; - status?: ResponseActionStatus; -}): Promise<ActionListApiResponse> => { - const endpointActionGenerator = new EndpointActionGenerator('seed'); - - const agentIds = _agentIds ?? [uuid.v4()]; - - const data: ActionListApiResponse['data'] = agentIds.map((id) => { - const actionIds = Array(actionCount) - .fill(1) - .map(() => uuid.v4()); - - const actionDetails: ActionListApiResponse['data'] = actionIds.map((actionId) => { - return endpointActionGenerator.generateActionDetails({ - agents: [id], - id: actionId, - isCompleted, - isExpired, - wasSuccessful, - status, - completedAt: isExpired ? undefined : new Date().toISOString(), - }); + describe('Statuses filter', () => { + const filterPrefix = '-statuses-filter'; + + it('should show a list of statuses when opened', () => { + render(); + userEvent.click(renderResult.getByTestId(`${testPrefix}${filterPrefix}-popoverButton`)); + const filterList = renderResult.getByTestId(`${testPrefix}${filterPrefix}-popoverList`); + expect(filterList).toBeTruthy(); + expect(filterList.querySelectorAll('ul>li').length).toEqual(3); + expect( + Array.from(filterList.querySelectorAll('ul>li')).map((option) => option.textContent) + ).toEqual(['Failed', 'Pending', 'Successful']); }); - return actionDetails; - })[0]; - return { - page, - pageSize, - startDate, - endDate, - elasticAgentIds: agentIds, - commands, - data, - userIds, - statuses: undefined, - total: data.length ?? 0, - }; -}; + it('should have `clear all` button `disabled` when no selected values', () => { + render(); + userEvent.click(renderResult.getByTestId(`${testPrefix}${filterPrefix}-popoverButton`)); + const clearAllButton = renderResult.getByTestId( + `${testPrefix}${filterPrefix}-clearAllButton` + ); + expect(clearAllButton.hasAttribute('disabled')).toBeTruthy(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx index d12fce4efcb956..79c99d62e2ff6e 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx @@ -25,7 +25,7 @@ import { import { euiStyled, css } from '@kbn/kibana-react-plugin/common'; import type { HorizontalAlignment, CriteriaWithPagination } from '@elastic/eui'; -import React, { memo, useCallback, useMemo, useState } from 'react'; +import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import type { ResponseActions, @@ -41,8 +41,15 @@ import { OUTPUT_MESSAGES, TABLE_COLUMN_NAMES, UX_MESSAGES } from './translations import { MANAGEMENT_PAGE_SIZE_OPTIONS } from '../../common/constants'; import { useTestIdGenerator } from '../../hooks/use_test_id_generator'; import { ActionsLogFilters } from './components/actions_log_filters'; -import { getActionStatus, getCommand, useDateRangePicker } from './components/hooks'; +import { + getActionStatus, + getUiCommand, + getCommandKey, + useDateRangePicker, +} from './components/hooks'; import { StatusBadge } from './components/status_badge'; +import { useActionHistoryUrlParams } from './components/use_action_history_url_params'; +import { useUrlPagination } from '../../hooks/use_url_pagination'; const emptyValue = getEmptyValue(); @@ -104,24 +111,48 @@ const StyledEuiCodeBlock = euiStyled(EuiCodeBlock).attrs({ `; export const ResponseActionsLog = memo< - Pick<EndpointActionListRequestQuery, 'agentIds'> & { showHostNames?: boolean } ->(({ agentIds, showHostNames = false }) => { + Pick<EndpointActionListRequestQuery, 'agentIds'> & { showHostNames?: boolean; isFlyout?: boolean } +>(({ agentIds, showHostNames = false, isFlyout = true }) => { + const { pagination: paginationFromUrlParams, setPagination: setPaginationOnUrlParams } = + useUrlPagination(); + const { + commands: commandsFromUrl, + statuses: statusesFromUrl, + startDate: startDateFromUrl, + endDate: endDateFromUrl, + } = useActionHistoryUrlParams(); + const getTestId = useTestIdGenerator('response-actions-list'); const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<{ [k: ActionListApiResponse['data'][number]['id']]: React.ReactNode; }>({}); const [queryParams, setQueryParams] = useState<EndpointActionListRequestQuery>({ - page: 1, - pageSize: 10, + page: isFlyout ? 1 : paginationFromUrlParams.page, + pageSize: isFlyout ? 10 : paginationFromUrlParams.pageSize, agentIds, commands: [], statuses: [], userIds: [], }); + // update query state from URL params + useEffect(() => { + if (!isFlyout) { + setQueryParams((prevState) => ({ + ...prevState, + commands: commandsFromUrl?.length + ? commandsFromUrl.map((commandFromUrl) => getCommandKey(commandFromUrl)) + : prevState.commands, + statuses: statusesFromUrl?.length + ? (statusesFromUrl as ResponseActionStatus[]) + : prevState.statuses, + })); + } + }, [commandsFromUrl, isFlyout, statusesFromUrl, setQueryParams]); + // date range picker state and handlers - const { dateRangePickerState, onRefreshChange, onTimeChange } = useDateRangePicker(); + const { dateRangePickerState, onRefreshChange, onTimeChange } = useDateRangePicker(isFlyout); // initial fetch of list data const { @@ -132,8 +163,8 @@ export const ResponseActionsLog = memo< refetch: reFetchEndpointActionList, } = useGetEndpointActionList({ ...queryParams, - startDate: dateRangePickerState.startDate, - endDate: dateRangePickerState.endDate, + startDate: isFlyout ? dateRangePickerState.startDate : startDateFromUrl, + endDate: isFlyout ? dateRangePickerState.endDate : endDateFromUrl, }); // handle auto refresh data @@ -191,7 +222,7 @@ export const ResponseActionsLog = memo< }) : undefined; - const command = getCommand(_command); + const command = getUiCommand(_command); const dataList = [ { title: OUTPUT_MESSAGES.expandSection.placedAt, @@ -294,7 +325,7 @@ export const ResponseActionsLog = memo< width: !showHostNames ? '21%' : '10%', truncateText: true, render: (_command: ActionListApiResponse['data'][number]['command']) => { - const command = getCommand(_command); + const command = getUiCommand(_command); return ( <EuiToolTip content={command} anchorClassName="eui-textTruncate"> <EuiText @@ -450,31 +481,53 @@ export const ResponseActionsLog = memo< // table pagination const tablePagination = useMemo(() => { + const pageIndex = isFlyout ? (queryParams.page || 1) - 1 : paginationFromUrlParams.page - 1; + const pageSize = isFlyout ? queryParams.pageSize || 10 : paginationFromUrlParams.pageSize; return { // this controls the table UI page // to match 0-based table paging - pageIndex: (queryParams.page || 1) - 1, - pageSize: queryParams.pageSize || 10, + pageIndex, + pageSize, totalItemCount, pageSizeOptions: MANAGEMENT_PAGE_SIZE_OPTIONS as number[], }; - }, [queryParams, totalItemCount]); + }, [ + isFlyout, + paginationFromUrlParams.page, + paginationFromUrlParams.pageSize, + queryParams.page, + queryParams.pageSize, + totalItemCount, + ]); // handle onChange const handleTableOnChange = useCallback( ({ page: _page }: CriteriaWithPagination<ActionListApiResponse['data'][number]>) => { // table paging is 0 based const { index, size } = _page; - setQueryParams((prevState) => ({ - ...prevState, - // adjust the page to conform to - // 1-based API page + // adjust the page to conform to + // 1-based API page + const pagingArgs = { page: index + 1, pageSize: size, - })); + }; + if (isFlyout) { + setQueryParams((prevState) => ({ + ...prevState, + ...pagingArgs, + })); + } else { + setQueryParams((prevState) => ({ + ...prevState, + ...pagingArgs, + })); + setPaginationOnUrlParams({ + ...pagingArgs, + }); + } reFetchEndpointActionList(); }, - [reFetchEndpointActionList, setQueryParams] + [isFlyout, reFetchEndpointActionList, setQueryParams, setPaginationOnUrlParams] ); // compute record ranges @@ -516,6 +569,7 @@ export const ResponseActionsLog = memo< return ( <> <ActionsLogFilters + isFlyout={isFlyout} dateRangePickerState={dateRangePickerState} isDataLoading={isFetching} onClick={reFetchEndpointActionList} diff --git a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx new file mode 100644 index 00000000000000..d22237be1fdf5d --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.test.tsx @@ -0,0 +1,316 @@ +/* + * 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 * as reactTestingLibrary from '@testing-library/react'; +import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; +import userEvent from '@testing-library/user-event'; +import { + type AppContextTestRender, + createAppRootMockRenderer, +} from '../../../../common/mock/endpoint'; +import { ResponseActionsListPage } from './response_actions_list_page'; +import type { ActionListApiResponse } from '../../../../../common/endpoint/types'; +import { MANAGEMENT_PATH } from '../../../../../common/constants'; +import { getActionListMock } from '../../../components/endpoint_response_actions_list/mocks'; + +let mockUseGetEndpointActionList: { + isFetched?: boolean; + isFetching?: boolean; + error?: null; + data?: ActionListApiResponse; + refetch: () => unknown; +}; +jest.mock('../../../hooks/endpoint/use_get_endpoint_action_list', () => { + const original = jest.requireActual('../../../hooks/endpoint/use_get_endpoint_action_list'); + return { + ...original, + useGetEndpointActionList: () => mockUseGetEndpointActionList, + }; +}); + +jest.mock('@kbn/kibana-react-plugin/public', () => { + const original = jest.requireActual('@kbn/kibana-react-plugin/public'); + return { + ...original, + useKibana: () => ({ + services: { + uiSettings: { + get: jest.fn().mockImplementation((key) => { + const get = (k: 'dateFormat' | 'timepicker:quickRanges') => { + const x = { + dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', + 'timepicker:quickRanges': [ + { + from: 'now/d', + to: 'now/d', + display: 'Today', + }, + { + from: 'now/w', + to: 'now/w', + display: 'This week', + }, + { + from: 'now-15m', + to: 'now', + display: 'Last 15 minutes', + }, + { + from: 'now-30m', + to: 'now', + display: 'Last 30 minutes', + }, + { + from: 'now-1h', + to: 'now', + display: 'Last 1 hour', + }, + { + from: 'now-24h', + to: 'now', + display: 'Last 24 hours', + }, + { + from: 'now-7d', + to: 'now', + display: 'Last 7 days', + }, + { + from: 'now-30d', + to: 'now', + display: 'Last 30 days', + }, + { + from: 'now-90d', + to: 'now', + display: 'Last 90 days', + }, + { + from: 'now-1y', + to: 'now', + display: 'Last 1 year', + }, + ], + }; + return x[k]; + }; + return get(key); + }), + }, + }, + }), + }; +}); + +describe('Action history page', () => { + const testPrefix = 'response-actions-list'; + + let render: () => ReturnType<AppContextTestRender['render']>; + let renderResult: ReturnType<typeof render>; + let history: AppContextTestRender['history']; + let mockedContext: AppContextTestRender; + + const refetchFunction = jest.fn(); + const baseMockedActionList = { + isFetched: true, + isFetching: false, + error: null, + refetch: refetchFunction, + }; + + beforeEach(async () => { + mockedContext = createAppRootMockRenderer(); + ({ history } = mockedContext); + render = () => (renderResult = mockedContext.render(<ResponseActionsListPage />)); + reactTestingLibrary.act(() => { + history.push(`${MANAGEMENT_PATH}/response_actions`); + }); + + mockUseGetEndpointActionList = { + ...baseMockedActionList, + data: await getActionListMock({ actionCount: 43 }), + }; + }); + + afterEach(() => { + mockUseGetEndpointActionList = { + ...baseMockedActionList, + }; + jest.clearAllMocks(); + }); + + describe('Read from URL params', () => { + it('should read and set paging values from URL params', () => { + reactTestingLibrary.act(() => { + history.push('/administration/action_history?page=3&pageSize=20'); + }); + render(); + const { getByTestId } = renderResult; + + expect(history.location.search).toEqual('?page=3&pageSize=20'); + expect(getByTestId('tablePaginationPopoverButton').textContent).toContain('20'); + expect(getByTestId('pagination-button-2').getAttribute('aria-current')).toStrictEqual('true'); + }); + + it('should read and set command filter values from URL params', () => { + const filterPrefix = 'actions-filter'; + reactTestingLibrary.act(() => { + history.push('/administration/action_history?commands=release,processes'); + }); + + render(); + const { getAllByTestId, getByTestId } = renderResult; + userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); + const allFilterOptions = getAllByTestId(`${filterPrefix}-option`); + + const selectedFilterOptions = allFilterOptions.reduce<string[]>((acc, option) => { + if (option.getAttribute('aria-checked') === 'true') { + acc.push(option.textContent?.split('-')[0].trim() as string); + } + return acc; + }, []); + + expect(selectedFilterOptions.length).toEqual(2); + expect(selectedFilterOptions).toEqual(['release', 'processes']); + expect(history.location.search).toEqual('?commands=release,processes'); + }); + + it('should read and set status filter values from URL params', () => { + const filterPrefix = 'statuses-filter'; + reactTestingLibrary.act(() => { + history.push('/administration/action_history?statuses=pending,failed'); + }); + + render(); + const { getAllByTestId, getByTestId } = renderResult; + userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); + const allFilterOptions = getAllByTestId(`${filterPrefix}-option`); + + const selectedFilterOptions = allFilterOptions.reduce<string[]>((acc, option) => { + if (option.getAttribute('aria-checked') === 'true') { + acc.push(option.textContent?.split('-')[0].trim() as string); + } + return acc; + }, []); + + expect(selectedFilterOptions.length).toEqual(2); + expect(selectedFilterOptions).toEqual(['Failed', 'Pending']); + expect(history.location.search).toEqual('?statuses=pending,failed'); + }); + + // TODO: add tests for hosts and users when those filters are added + + it('should read and set relative date ranges filter values from URL params', () => { + reactTestingLibrary.act(() => { + history.push('/administration/action_history?startDate=now-23m&endDate=now-1m'); + }); + + render(); + const { getByTestId } = renderResult; + + expect(getByTestId('superDatePickerstartDatePopoverButton').textContent).toEqual( + '~ 23 minutes ago' + ); + expect(getByTestId('superDatePickerendDatePopoverButton').textContent).toEqual( + '~ a minute ago' + ); + expect(history.location.search).toEqual('?startDate=now-23m&endDate=now-1m'); + }); + + it('should read and set absolute date ranges filter values from URL params', () => { + const startDate = '2022-09-12T11:00:00.000Z'; + const endDate = '2022-09-12T11:30:33.000Z'; + reactTestingLibrary.act(() => { + history.push(`/administration/action_history?startDate=${startDate}&endDate=${endDate}`); + }); + + const { getByTestId } = render(); + + expect(getByTestId('superDatePickerstartDatePopoverButton').textContent).toEqual( + 'Sep 12, 2022 @ 07:00:00.000' + ); + expect(getByTestId('superDatePickerendDatePopoverButton').textContent).toEqual( + 'Sep 12, 2022 @ 07:30:33.000' + ); + expect(history.location.search).toEqual(`?startDate=${startDate}&endDate=${endDate}`); + }); + }); + + describe('Set selected/set values to URL params', () => { + it('should set selected page number to URL params', () => { + render(); + const { getByTestId } = renderResult; + + userEvent.click(getByTestId('pagination-button-1')); + expect(history.location.search).toEqual('?page=2&pageSize=10'); + }); + + it('should set selected pageSize value to URL params', () => { + render(); + const { getByTestId } = renderResult; + + userEvent.click(getByTestId('tablePaginationPopoverButton')); + const pageSizeOption = getByTestId('tablePagination-20-rows'); + pageSizeOption.style.pointerEvents = 'all'; + userEvent.click(pageSizeOption); + + expect(history.location.search).toEqual('?page=1&pageSize=20'); + }); + + it('should set selected command filter options to URL params ', () => { + const filterPrefix = 'actions-filter'; + render(); + const { getAllByTestId, getByTestId } = renderResult; + userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); + const allFilterOptions = getAllByTestId(`${filterPrefix}-option`); + + allFilterOptions.forEach((option) => { + option.style.pointerEvents = 'all'; + userEvent.click(option); + }); + + expect(history.location.search).toEqual( + '?commands=isolate%2Crelease%2Ckill-process%2Csuspend-process%2Cprocesses' + ); + }); + + it('should set selected status filter options to URL params ', () => { + const filterPrefix = 'statuses-filter'; + render(); + const { getAllByTestId, getByTestId } = renderResult; + userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`)); + const allFilterOptions = getAllByTestId(`${filterPrefix}-option`); + + allFilterOptions.forEach((option) => { + option.style.pointerEvents = 'all'; + userEvent.click(option); + }); + + expect(history.location.search).toEqual('?statuses=failed%2Cpending%2Csuccessful'); + }); + + // TODO: add tests for hosts and users when those filters are added + + it('should set selected relative date range filter options to URL params ', async () => { + const { getByTestId } = render(); + const quickMenuButton = getByTestId('superDatePickerToggleQuickMenuButton'); + const startDatePopoverButton = getByTestId(`superDatePickerShowDatesButton`); + + // shows 24 hours at first + expect(startDatePopoverButton).toHaveTextContent('Last 24 hours'); + + // pick another relative date + userEvent.click(quickMenuButton); + await waitForEuiPopoverOpen(); + userEvent.click(getByTestId('superDatePickerCommonlyUsed_Last_15 minutes')); + expect(startDatePopoverButton).toHaveTextContent('Last 15 minutes'); + + expect(history.location.search).toEqual('?endDate=now&startDate=now-15m'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx index 23b3da831ddac8..2b8d21f8f0ac18 100644 --- a/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/response_actions/view/response_actions_list_page.tsx @@ -18,7 +18,7 @@ export const ResponseActionsListPage = () => { title={ACTION_HISTORY} subtitle={UX_MESSAGES.pageSubTitle} > - <ResponseActionsLog showHostNames={true} /> + <ResponseActionsLog showHostNames={true} isFlyout={false} /> </AdministrationListPage> ); }; From efbf9e4d31c7fea741749df0abb28107aed4d16b Mon Sep 17 00:00:00 2001 From: Lisa Cawley <lcawley@elastic.co> Date: Tue, 13 Sep 2022 07:35:21 -0700 Subject: [PATCH 117/144] [DOCS] Augment create and run connector APIs with ServiceNow details (#140348) --- .../actions-and-connectors/create.asciidoc | 85 ++++- .../actions-and-connectors/execute.asciidoc | 350 ++++++++++++++++-- x-pack/plugins/actions/README.md | 11 +- 3 files changed, 420 insertions(+), 26 deletions(-) diff --git a/docs/api/actions-and-connectors/create.asciidoc b/docs/api/actions-and-connectors/create.asciidoc index e8533e0561ccee..c33cbdd77232c3 100644 --- a/docs/api/actions-and-connectors/create.asciidoc +++ b/docs/api/actions-and-connectors/create.asciidoc @@ -83,6 +83,41 @@ For more information, refer to <<index-action-type>>. For more information, refer to <<jira-action-type>>. ===== +.{sn-itom}, {sn-itsm}, and {sn-sir} connectors +[%collapsible%open] +===== +`apiUrl`:: +(Required, string) The {sn} instance URL. + +`clientId`:: +(Required^*^, string) The client ID assigned to your OAuth application. This +property is required when `isOAuth` is `true`. + +`isOAuth`:: +(Optional, string) The type of authentication to use. The default value is +`false`, which means basic authentication is used instead of open authorization +(OAuth). + +`jwtKeyId`:: +(Required^*^, string) The key identifier assigned to the JWT verifier map of +your OAuth application. This property is required when `isOAuth` is `true`. + +`userIdentifierValue`:: +(Required^*^, string) The identifier to use for OAuth authentication. This +identifier should be the user field you selected when you created an OAuth +JWT API endpoint for external clients in your {sn} instance. For example, if +the selected user field is `Email`, the user identifier should be the user's +email address. This property is required when `isOAuth` is `true`. + +`usesTableApi`:: +(Optional, string) Determines whether the connector uses the Table API or the +Import Set API. This property is supported only for {sn-itsm} and {sn-sir} +connectors. ++ +NOTE: If this property is set to false, the Elastic application should be +installed in {sn}. +===== + .{swimlane} connectors [%collapsible%open] ===== @@ -373,7 +408,7 @@ For more configuration properties, refer to <<action-types>>. `connector_type_id`:: (Required, string) The connector type ID for the connector. For example, -`.cases-webhook`, `.index`, `.jira`, or `.server-log`. +`.cases-webhook`, `.index`, `.jira`, `.server-log`, or `.servicenow-itom`. `name`:: (Required, string) The display name for the connector. @@ -412,6 +447,31 @@ authentication. (Required, string) The account email for HTTP Basic authentication. ===== +.{sn-itom}, {sn-itsm}, and {sn-sir} connectors +[%collapsible%open] +===== +`clientSecret`:: +(Required^*^, string) The client secret assigned to your OAuth application. This +property is required when `isOAuth` is `true`. + +`password`:: +(Required^*^, string) The password for HTTP basic authentication. This property +is required when `isOAuth` is `false`. + +`privateKey`:: +(Required^*^, string) The RSA private key that you created for use in {sn}. This +property is required when `isOAuth` is `true`. + +privateKeyPassword:: +(Required^*^, string) The password for the RSA private key. This property is +required when `isOAuth` is `true` and you set a password on your private key. + +`username`:: +(Required^*^, string) The username for HTTP basic authentication. This property +is required when `isOAuth` is `false`. + +===== + .{swimlane} connectors [%collapsible%open] ===== @@ -516,6 +576,29 @@ POST api/actions/connector -------------------------------------------------- // KIBANA +Create an {sn-itom} connector that uses open authorization: + +[source,sh] +-------------------------------------------------- +POST api/actions/connector +{ + "name": "my-itom-connector", + "connector_type_id": ".servicenow-itom", + "config": { + "apiUrl": "https://exmaple.service-now.com/", + "clientId": "abcdefghijklmnopqrstuvwxyzabcdef", + "isOAuth": "true", + "jwtKeyId": "fedcbazyxwvutsrqponmlkjihgfedcba", + "userIdentifierValue": "testuser@email.com" + }, + "secrets": { + "clientSecret": "secretsecret", + "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nprivatekeyhere\n-----END RSA PRIVATE KEY-----" + } +} +-------------------------------------------------- +// KIBANA + Create a {swimlane} connector: [source,sh] diff --git a/docs/api/actions-and-connectors/execute.asciidoc b/docs/api/actions-and-connectors/execute.asciidoc index 29e9bfa4cf224f..e477d7237c2737 100644 --- a/docs/api/actions-and-connectors/execute.asciidoc +++ b/docs/api/actions-and-connectors/execute.asciidoc @@ -50,19 +50,23 @@ depending on the connector type. For information about the parameter properties, refer to <<action-types>>. + -- -.Index connectors +.`Params` properties [%collapsible%open] ==== + +.Index connectors +[%collapsible%open] +===== `documents`:: (Required, array of objects) The documents to index in JSON format. For more information, refer to {kibana-ref}/index-action-type.html[Index connector and action]. -==== +===== .Jira connectors [%collapsible%open] -==== +===== `subAction`:: (Required, string) The action to test. Valid values include: `fieldsByIssueType`, `getFields`, `getIncident`, `issue`, `issues`, `issueTypes`, and `pushToService`. @@ -74,55 +78,55 @@ on the `subAction` value. This object is not required when `subAction` is + .Properties when `subAction` is `fieldsByIssueType` [%collapsible%open] -===== +====== `id`::: (Required, string) The Jira issue type identifier. For example, `10024`. -===== +====== + .Properties when `subAction` is `getIncident` [%collapsible%open] -===== +====== `externalId`::: (Required, string) The Jira issue identifier. For example, `71778`. -===== +====== + .Properties when `subAction` is `issue` [%collapsible%open] -===== +====== `id`::: (Required, string) The Jira issue identifier. For example, `71778`. -===== +====== + .Properties when `subAction` is `issues` [%collapsible%open] -===== +====== `title`::: (Required, string) The title of the Jira issue. -===== +====== + .Properties when `subAction` is `pushToService` [%collapsible%open] -===== -comments::: +====== +`comments`::: (Optional, array of objects) Additional information that is sent to Jira. + .Properties of `comments` [%collapsible%open] -====== -comment:::: +======= +`comment`:::: (string) A comment related to the incident. For example, describe how to troubleshoot the issue. -commentId:::: +`commentId`:::: (integer) A unique identifier for the comment. -====== +======= -incident::: +`incident`::: (Required, object) Information necessary to create or update a Jira incident. + .Properties of `incident` [%collapsible%open] -====== +======= `description`:::: (Optional, string) The details about the incident. @@ -151,22 +155,288 @@ types of issues. `title`:::: (Optional, string) A title for the incident, used for searching the contents of the knowledge base. +======= ====== -===== For more information, refer to {kibana-ref}/jira-action-type.html[{jira} connector and action]. -==== +===== + +.{sn-itom} connectors +[%collapsible%open] +===== +`subAction`:: +(Required, string) The action to test. Valid values include: `addEvent` and +`getChoices`. + +`subActionParams`:: +(Required^*^, object) The set of configuration properties, which vary depending +on the `subAction` value. ++ +.Properties when `subAction` is `addEvent` +[%collapsible%open] +====== +`additional_info`:::: +(Optional, string) Additional information about the event. + +`description`:::: +(Optional, string) The details about the event. + +`event_class`:::: +(Optional, string) A specific instance of the source. + +`message_key`:::: +(Optional, string) All actions sharing this key are associated with the same +{sn} alert. The default value is `<rule ID>:<alert instance ID>`. + +`metric_name`:::: +(Optional, string) The name of the metric. + +`node`:::: +(Optional, string) The host that the event was triggered for. + +`resource`:::: +(Optional, string) The name of the resource. + +`severity`:::: +(Optional, string) The severity of the event. + +`source`:::: +(Optional, string) The name of the event source type. + +`time_of_event`:::: +(Optional, string) The time of the event. + +`type`:::: +(Optional, string) The type of event. +====== ++ +.Properties when `subAction` is `getChoices` +[%collapsible%open] +====== +`fields`:::: +(Required, array of strings) An array of fields. For example, `["severity"]`. +====== +===== + +.{sn-itsm} connectors +[%collapsible%open] +===== +`subAction`:: +(Required, string) The action to test. Valid values include: `getFields`, +`getIncident`, `getChoices`, and `pushToService`. + +`subActionParams`:: +(Required^*^, object) The set of configuration properties, which vary depending +on the `subAction` value. This object is not required when `subAction` is +`getFields`. ++ +.Properties when `subAction` is `getChoices` +[%collapsible%open] +====== +`fields`:::: +(Required, array of strings) An array of fields. For example, `["category","impact"]`. +====== ++ +.Properties when `subAction` is `getIncident` +[%collapsible%open] +====== +`externalId`:::: +(Required, string) The {sn-itsm} issue identifier. +====== ++ +.Properties when `subAction` is `pushToService` +[%collapsible%open] +====== +`comments`::: +(Optional, array of objects) Additional information that is sent to {sn-sir}. ++ +.Properties of `comments` +[%collapsible%open] +======= +`comment`:::: +(string) A comment related to the incident. For example, describe how to +troubleshoot the issue. + +`commentId`:::: +(integer) A unique identifier for the comment. + +//// +version:::: +(string) TBD +//// +======= + +`incident`::: +(Required, object) Information necessary to create or update a {sn-sir} incident. ++ +.Properties of `incident` +[%collapsible%open] +======= +`category`:::: +(Optional, string) The category of the incident. + +`correlation_display`:::: +(Optional, string) A descriptive label of the alert for correlation purposes in +{sn}. + +`correlation_id`:::: +(Optional, string) The correlation identifier for the security incident. +Connectors using the same correlation ID are associated with the same {sn} +incident. This value determines whether a new {sn} incident is created or an +existing one is updated. Modifying this value is optional; if not modified, the +rule ID and alert ID are combined as `{{ruleID}}:{{alert ID}}` to form the +correlation ID value in {sn}. The maximum character length for this value is 100 +characters. ++ +NOTE: Using the default configuration of `{{ruleID}}:{{alert ID}}` ensures +that {sn} creates a separate incident record for every generated alert that uses +a unique alert ID. If the rule generates multiple alerts that use the same alert +IDs, {sn} creates and continually updates a single incident record for the alert. + +`description`:::: +(Optional, string) The details about the incident. + +`externalId`:::: +(Optional, string) The {sn-itsm} issue identifier. If present, the incident is +updated. Otherwise, a new incident is created. + +`impact`:::: +(Optional, string) The impact in {sn-itsm}. + +`severity`:::: +(Optional, string) The severity of the incident. + +`short_description`:::: +(Required, string) A short description for the incident, used for searching the +contents of the knowledge base. + +`subcategory`:::: +(Optional, string) The subcategory in {sn-itsm}. + +`urgency`:::: +(Optional, string) The urgency in {sn-itsm}. +======= +====== +===== + +.{sn-sir} connectors +[%collapsible%open] +===== +`subAction`:: +(Required, string) The action to test. Valid values include: `getFields`, +`getIncident`, `getChoices`, and `pushToService`. + +`subActionParams`:: +(Required^*^, object) The set of configuration properties, which vary depending +on the `subAction` value. This object is not required when `subAction` is +`getFields`. ++ +.Properties when `subAction` is `getChoices` +[%collapsible%open] +====== +`fields`:::: +(Required, array of strings) An array of fields. For example, `["priority","category"]`. +====== ++ +.Properties when `subAction` is `getIncident` +[%collapsible%open] +====== +`externalId`:::: +(Required, string) The {sn-sir} issue identifier. +====== ++ +.Properties when `subAction` is `pushToService` +[%collapsible%open] +====== +`comments`::: +(Optional, array of objects) Additional information that is sent to {sn-sir}. ++ +.Properties of `comments` +[%collapsible%open] +======= +`comment`:::: +(string) A comment related to the incident. For example, describe how to +troubleshoot the issue. + +`commentId`:::: +(integer) A unique identifier for the comment. + +//// +`version`:::: +(string) TBD +//// +======= + +`incident`::: +(Required, object) Information necessary to create or update a {sn-sir} incident. ++ +.Properties of `incident` +[%collapsible%open] +======= +`category`:::: +(Optional, string) The category of the incident. + +`correlation_display`:::: +(Optional, string) A descriptive label of the alert for correlation purposes in +{sn}. + +`correlation_id`:::: +(Optional, string) The correlation identifier for the security incident. +Connectors using the same correlation ID are associated with the same {sn} +incident. This value determines whether a new {sn} incident is created or an +existing one is updated. Modifying this value is optional; if not modified, the +rule ID and alert ID are combined as `{{ruleID}}:{{alert ID}}` to form the +correlation ID value in {sn}. The maximum character length for this value is 100 +characters. ++ +NOTE: Using the default configuration of `{{ruleID}}:{{alert ID}}` ensures that +{sn} creates a separate incident record for every generated alert that uses a +unique alert ID. If the rule generates multiple alerts that use the same alert +IDs, {sn} creates and continually updates a single incident record for the alert. + +`description`:::: +(Optional, string) The details about the incident. + +`dest_ip`:::: +(Optional, string or array of strings) A list of destination IP addresses related +to the security incident. The IPs are added as observables to the security incident. + +`externalId`:::: +(Optional, string) The {sn-sir} issue identifier. If present, the incident is +updated. Otherwise, a new incident is created. + +`malware_hash`:::: +(Optional, string or array of strings) A list of malware URLs related to the +security incident. The URLs are added as observables to the security incident. + +`priority`:::: +(Optional, string) The priority of the incident. + +`short_description`:::: +(Required, string) A short description for the incident, used for searching the +contents of the knowledge base. + +`source_ip`:::: +(Optional, string or array of strings) A list of source IP addresses related to +the security incident. The IPs are added as observables to the security incident. + +`subcategory`:::: +(Optional, string) The subcategory of the incident. +======= +====== +===== .Server log connectors [%collapsible%open] -==== +===== `level`:: (Optional, string) The log level of the message: `trace`, `debug`, `info`, `warn`, `error`, or `fatal`. Defaults to `info`. `message`:: (Required, string) The message to log. +===== ==== -- @@ -277,4 +547,40 @@ The API returns the following: ], "connector_id":"b3aad810-edbe-11ec-82d1-11348ecbf4a6" } +-------------------------------------------------- + +Retrieve the list of choices for a {sn-itom} connector: + +[source,sh] +-------------------------------------------------- +POST api/actions/connector/9d9be270-2fd2-11ed-b0e0-87533c532698/_execute +{ + "params": { + "subAction": "getChoices", + "subActionParams": { + "fields": [ "severity","urgency" ] + } + } +} +-------------------------------------------------- +// KIBANA + +The API returns the severity and urgency choices, for example: + +[source,sh] +-------------------------------------------------- +{ + "status": "ok", + "data":[ + {"dependent_value":"","label":"Critical","value":"1","element":"severity"}, + {"dependent_value":"","label":"Major","value":"2","element":"severity"}, + {"dependent_value":"","label":"Minor","value":"3","element":"severity"}, + {"dependent_value":"","label":"Warning","value":"4","element":"severity"}, + {"dependent_value":"","label":"OK","value":"5","element":"severity"}, + {"dependent_value":"","label":"Clear","value":"0","element":"severity"}, + {"dependent_value":"","label":"1 - High","value":"1","element":"urgency"}, + {"dependent_value":"","label":"2 - Medium","value":"2","element":"urgency"}, + {"dependent_value":"","label":"3 - Low","value":"3","element":"urgency"}], + "connector_id":"9d9be270-2fd2-11ed-b0e0-87533c532698" +} -------------------------------------------------- \ No newline at end of file diff --git a/x-pack/plugins/actions/README.md b/x-pack/plugins/actions/README.md index 7d9dc9d4060350..213ec6d8f23ce5 100644 --- a/x-pack/plugins/actions/README.md +++ b/x-pack/plugins/actions/README.md @@ -260,7 +260,9 @@ In addition to the documented configurations, several built in action type offer ## ServiceNow ITSM -The [ServiceNow ITSM user documentation `params`](https://www.elastic.co/guide/en/kibana/master/servicenow-action-type.html) lists configuration properties for the `pushToService` subaction. In addition, several other subaction types are available. +Refer to the [Run connector API documentation](https://www.elastic.co/guide/en/kibana/master/execute-connector-api.html#execute-connector-api-request-body) +for the full list of properties. + ### `params` | Property | Description | Type | @@ -311,7 +313,8 @@ No parameters for the `getFields` subaction. Provide an empty object `{}`. ## ServiceNow Sec Ops -The [ServiceNow SecOps user documentation `params`](https://www.elastic.co/guide/en/kibana/master/servicenow-sir-action-type.html) lists configuration properties for the `pushToService` subaction. In addition, several other subaction types are available. +Refer to the [Run connector API documentation](https://www.elastic.co/guide/en/kibana/master/execute-connector-api.html#execute-connector-api-request-body) +for the full list of properties. ### `params` @@ -364,7 +367,9 @@ No parameters for the `getFields` subaction. Provide an empty object `{}`. --- ## ServiceNow ITOM -The [ServiceNow ITOM user documentation `params`](https://www.elastic.co/guide/en/kibana/master/servicenow-itom-action-type.html) lists configuration properties for the `addEvent` subaction. In addition, several other subaction types are available. +Refer to the [Run connector API documentation](https://www.elastic.co/guide/en/kibana/master/execute-connector-api.html#execute-connector-api-request-body) +for the full list of properties. + ### `params` | Property | Description | Type | From 1fcd75a70662b911c9d0e7edf675c4a2ddf9e921 Mon Sep 17 00:00:00 2001 From: Nodir Latipov <nodir.latypov@gmail.com> Date: Tue, 13 Sep 2022 19:36:52 +0500 Subject: [PATCH 118/144] [Unified Search] Create a filter builder component which works with nested OR/AND filters (#136815) * init: add filters editor component * apply some changes * add storybook * push some changes * push some logic * push some logic * push some logic * add reducer * add more complext filters * feat: add moveFilter action * feat: add input form for filters editor filter item * feat: add filter UI * fix: storybook * fix UI: edit filter component * style: add panel to filter * feat: update style * style: add style for dilimeter * refact: filter item * style: added style for odd filter group * feat: added add filter action * feat: update add filter in filter group * feat: added remove filter * refact: updated add filter and remove filter * feat: added addFilterGroup * feat: updated addFilterGroup with empty filter * refact: utils * refact: seperte filters editor filter (field input) * refact: seperte filters editor filter (operator input) * refact: filters editor * refact: filters editor (params field * push some changes * push some cleanup * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * move filters to __mock__ folder * feat: update handle filter item * add getFilterByPath method * remove addFilterGroupWithFilter * remove addFilterGroupWithFilter * add some logic * add addFilter support * update styles * add removeFilter * fix types * refact: cleanup any * refact: filter item * fix: data for show filter item * refact: cleanup useState in filters editor * refact: filter edit * style: fix UI in filter group * add disableOR/AND/DELETE params * add preparation for d2d * fix: show filter item after add filter * update filterGroup * fix: drag and drop * do cleanup * feat: add logic for drag&drop * style: filter item * apply new structure * push some logic * fix some cases * feat: udpated updateFilter * feat: added update field in filter * feat: added update params in filter * feat: added update operator in filter * feat: added update operator in filter--amend * style: add uiPanel into filterItem * feat: added translate * refact: filter item * feat: updated filter item for exists type * feat: added unique key for filter Item * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * fix: update params * fix: update params * style: params input * fix: disabled for phrase value input * feat: added filter params update * refact: change type * feat: index for EuiDraggable * refact: rename properties * feat: added useCallback * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * refact: cleanup code * refact: minor changes * style: change show label for filter phrase(s) * dandd preparation * feat: add ref to panel * fix merge configct * refact: destination => dropTarget and added it into context * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * feat: udpate d&d logic * feat: added chagne cursor for OR filter * feat: add change cursor in d&d * feat: add change cursor in d&d * style: changed cursor view svg * feat: added disable or conditional in d&d * feat: moved filter_editor -> shared_component * style: used emotion react * move filter_label * rename filters editor -> filters builder * feat: added hideOr * feat: added hideOr * feat: added sisabled and drop if depth = maxDepth * feat: update disable isCombine * feat: rename filtersEditor->filtersBulder * feat: added new storybook * feat: remove autocomplete service * refact: updated filterBuilder * feat: updated css style * fix: jest test * refact: move snapshot for filter label * feat: update search bar * refact: filter builder utils * fix: update filter * refact: update filter builder * fix: autocomplete test * fix: test * fix: jest test * fix: d&d * test: update test * test: update test * fix: functional tests: * fix: check type * refact: move filter * refact: minor * feat: move filter editor from shared components to filter bar * minor update * fix: check type * fix: type check * fix: d&d * fix: d&d * feat: resolve comment * minor fix * fix: d&d * fix: type check test * fix: check type test * feat: covered new case with d&d * feat: covered new case with d&d * feat: covered new case with d&d * refact: move filter * fix: bug with storybook * refact: remove todo comment * fix normalizeFilters method * refact: ref to FilterEditor * refact: moved filters_builder to up level * fix: update operator * refact: key for list * refact: did FiltersBuilder lazy * feat: move cvg to under component and rename * feat: resolve comment * feat: added validation for filter build item into params enter uncorrect date * test: added test for normalizeFilters * feat: update test * style: fix UI * refact: utils files in filters builder * style: filter group background * style: filter group * doc: added comment to methods in utils * style: fix border * style: fix border * fix: UI * feat: added backgroud for gray filter group * temp changes * fix some styles * feat: added devider and margin * style: change style -> css * style: change style -> css * refact: style * refact: style * fix: test * refact: style * feat: added rule for show border * style: UI * style: show OR delimiter * style: margin for AND delimiter * feat: update show border for first level * feat: update styles * style: fix padding for panel --- src/plugins/data/public/index.ts | 1 - src/plugins/data/public/types.ts | 16 +- .../dataview_picker/change_dataview.tsx | 4 +- .../filter_editor/filter_editor.test.tsx | 5 +- .../{index.tsx => filter_editor.tsx} | 62 +- .../public/filter_bar/filter_editor/index.ts | 41 ++ .../filter_editor/lib/filter_editor_utils.ts | 2 +- .../filter_editor/lib}/helpers.test.ts | 0 .../filter_editor/lib}/helpers.ts | 4 +- .../filter_bar/filter_editor/lib/index.ts | 29 + .../filter_editor/phrase_suggestor.tsx | 7 +- .../filter_editor/phrase_value_input.tsx | 32 +- .../filter_editor/phrases_values_input.tsx | 49 +- .../filter_editor/range_value_input.tsx | 7 + .../filter_editor/value_input_type.tsx | 13 +- .../filter_bar/filter_item/filter_item.tsx | 2 +- .../filter_bar/filter_item/filter_items.tsx | 4 +- .../__snapshots__/filter_label.test.tsx.snap | 0 .../filter_label.test.tsx | 0 .../lib => filter_label}/filter_label.tsx | 4 +- .../public/filter_bar/index.tsx | 2 +- .../filters_builder/__mock__/filters.ts | 630 ++++++++++++++++++ .../__stories__/filter_builder.stories.tsx | 188 ++++++ .../public/filters_builder/assets/add.svg | 33 + .../public/filters_builder/assets/or.svg | 33 + .../filters_builder/filters_builder.tsx | 126 ++++ .../filters_builder_context.ts | 26 + .../filters_builder_filter_group.tsx | 149 +++++ .../filters_builder_filter_item.tsx | 317 +++++++++ ...ilters_builder_filter_item_field_input.tsx | 51 ++ ...ers_builder_filter_item_operator_input.tsx | 61 ++ ...ters_builder_filter_item_params_editor.tsx | 113 ++++ .../filters_builder_filter_item/index.ts | 9 + .../filters_builder_reducer.ts | 99 +++ .../filters_builder/filters_builder_types.ts | 10 + .../filters_builder_utils.test.ts | 261 ++++++++ .../filters_builder/filters_builder_utils.ts | 360 ++++++++++ .../public/filters_builder/index.ts | 22 + src/plugins/unified_search/public/index.ts | 6 +- src/plugins/unified_search/public/plugin.ts | 6 +- .../filter_editor_wrapper.tsx | 4 +- .../query_bar_menu_panels.tsx | 5 +- .../query_bar_top_row.test.tsx | 7 +- .../query_string_input/query_bar_top_row.tsx | 5 +- .../query_string_input.test.tsx | 9 +- .../query_string_input/query_string_input.tsx | 13 +- .../text_based_languages_editor/index.tsx | 4 +- .../saved_query_management_list.tsx | 5 +- .../public/search_bar/create_search_bar.tsx | 6 +- .../public/search_bar/search_bar.tsx | 4 +- src/plugins/unified_search/public/services.ts | 4 - src/plugins/unified_search/public/types.ts | 21 +- .../unified_search/public/utils/index.ts | 8 + .../unified_search/public/utils/or_filter.ts | 47 ++ .../guidance_panel/guidance_panel.tsx | 4 +- .../public/components/search_bar.test.tsx | 7 - .../graph/public/components/search_bar.tsx | 4 +- .../components/query_bar/index.test.tsx | 7 - .../actions_log_date_range_picker.tsx | 5 +- .../timeline/query_bar/index.test.tsx | 7 - .../legacy_uptime/pages/overview.test.tsx | 7 - .../components/query_bar/query_bar.test.tsx | 7 +- 62 files changed, 2791 insertions(+), 183 deletions(-) rename src/plugins/unified_search/public/filter_bar/filter_editor/{index.tsx => filter_editor.tsx} (90%) create mode 100644 src/plugins/unified_search/public/filter_bar/filter_editor/index.ts rename src/plugins/unified_search/public/{utils => filter_bar/filter_editor/lib}/helpers.test.ts (100%) rename src/plugins/unified_search/public/{utils => filter_bar/filter_editor/lib}/helpers.ts (92%) create mode 100644 src/plugins/unified_search/public/filter_bar/filter_editor/lib/index.ts rename src/plugins/unified_search/public/filter_bar/{filter_editor/lib => filter_label}/__snapshots__/filter_label.test.tsx.snap (100%) rename src/plugins/unified_search/public/filter_bar/{filter_editor/lib => filter_label}/filter_label.test.tsx (100%) rename src/plugins/unified_search/public/filter_bar/{filter_editor/lib => filter_label}/filter_label.tsx (94%) create mode 100644 src/plugins/unified_search/public/filters_builder/__mock__/filters.ts create mode 100644 src/plugins/unified_search/public/filters_builder/__stories__/filter_builder.stories.tsx create mode 100644 src/plugins/unified_search/public/filters_builder/assets/add.svg create mode 100644 src/plugins/unified_search/public/filters_builder/assets/or.svg create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder.tsx create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_context.ts create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_filter_group.tsx create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item.tsx create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_field_input.tsx create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_operator_input.tsx create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_params_editor.tsx create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/index.ts create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_reducer.ts create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_types.ts create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_utils.test.ts create mode 100644 src/plugins/unified_search/public/filters_builder/filters_builder_utils.ts create mode 100644 src/plugins/unified_search/public/filters_builder/index.ts create mode 100644 src/plugins/unified_search/public/utils/or_filter.ts diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index ed50d78f4de3c1..c8eefbdd92c6e0 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -291,7 +291,6 @@ export function plugin(initializerContext: PluginInitializerContext<ConfigSchema export type { DataPublicPluginSetup, DataPublicPluginStart, - IDataPluginServices, DataPublicPluginStartActions, } from './types'; diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 58b66bb74b5e3c..fe803b76364d88 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -6,14 +6,12 @@ * Side Public License, v 1. */ -import { CoreStart } from '@kbn/core/public'; import { BfetchPublicSetup } from '@kbn/bfetch-plugin/public'; -import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { ExpressionsSetup } from '@kbn/expressions-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { FieldFormatsSetup, FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; +import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import { Setup as InspectorSetup } from '@kbn/inspector-plugin/public'; import { ScreenshotModePluginStart } from '@kbn/screenshot-mode-plugin/public'; import { SharePluginStart } from '@kbn/share-plugin/public'; @@ -102,15 +100,3 @@ export interface DataPublicPluginStart { nowProvider: NowProviderPublicContract; } - -export interface IDataPluginServices extends Partial<CoreStart> { - appName: string; - uiSettings: CoreStart['uiSettings']; - savedObjects: CoreStart['savedObjects']; - notifications: CoreStart['notifications']; - application: CoreStart['application']; - http: CoreStart['http']; - storage: IStorageWrapper; - data: DataPublicPluginStart; - usageCollection?: UsageCollectionStart; -} diff --git a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx index 44c281560fd545..94c869bb54a1c8 100644 --- a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx +++ b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx @@ -26,8 +26,8 @@ import { EuiToolTip, } from '@elastic/eui'; import type { DataViewListItem } from '@kbn/data-views-plugin/public'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import type { IUnifiedSearchPluginServices } from '../types'; import type { DataViewPickerPropsExtended } from '.'; import { DataViewsList } from './dataview_list'; import type { TextBasedLanguagesListProps } from './text_languages_list'; @@ -82,7 +82,7 @@ export function ChangeDataView({ const [isTextLangTransitionModalVisible, setIsTextLangTransitionModalVisible] = useState(false); const [selectedDataViewId, setSelectedDataViewId] = useState(currentDataViewId); - const kibana = useKibana<IDataPluginServices>(); + const kibana = useKibana<IUnifiedSearchPluginServices>(); const { application, data, storage } = kibana.services; const styles = changeDataViewStyles({ fullWidth: trigger.fullWidth }); const [isTextLangTransitionModalDismissed, setIsTextLangTransitionModalDismissed] = useState(() => diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.test.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.test.tsx index 87d0eca815cd80..cac21f97329046 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.test.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.test.tsx @@ -7,7 +7,8 @@ */ import { registerTestBed, TestBed } from '@kbn/test-jest-helpers'; -import { FilterEditor, Props } from '.'; +import type { FilterEditorProps } from '.'; +import { FilterEditor } from '.'; import React from 'react'; jest.mock('@kbn/kibana-react-plugin/public', () => { @@ -32,7 +33,7 @@ describe('<FilterEditor />', () => { let testBed: TestBed; beforeEach(async () => { - const defaultProps: Omit<Props, 'intl'> = { + const defaultProps: Omit<FilterEditorProps, 'intl'> = { filter: { meta: { type: 'phase', diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/index.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.tsx similarity index 90% rename from src/plugins/unified_search/public/filter_bar/filter_editor/index.tsx rename to src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.tsx index 0bdda65b32c9d0..cdf4af1746e5c9 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/index.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/filter_editor.tsx @@ -48,8 +48,9 @@ import { Operator } from './lib/filter_operators'; import { PhraseValueInput } from './phrase_value_input'; import { PhrasesValuesInput } from './phrases_values_input'; import { RangeValueInput } from './range_value_input'; +import { getFieldValidityAndErrorMessage } from './lib/helpers'; -export interface Props { +export interface FilterEditorProps { filter: Filter; indexPatterns: DataView[]; onSubmit: (filter: Filter) => void; @@ -84,8 +85,8 @@ const updateButtonLabel = i18n.translate('unifiedSearch.filter.filterEditor.upda defaultMessage: 'Update filter', }); -class FilterEditorUI extends Component<Props, State> { - constructor(props: Props) { +class FilterEditorUI extends Component<FilterEditorProps, State> { + constructor(props: FilterEditorProps) { super(props); this.state = { selectedIndexPattern: this.getIndexPatternFromFilter(), @@ -356,32 +357,55 @@ class FilterEditorUI extends Component<Props, State> { return ''; } + const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage( + this.state.selectedField, + this.state.params + ); + switch (this.state.selectedOperator.type) { case 'exists': return ''; case 'phrase': return ( - <PhraseValueInput - indexPattern={indexPattern} - field={this.state.selectedField} - value={this.state.params} - onChange={this.onParamsChange} - data-test-subj="phraseValueInput" - timeRangeForSuggestionsOverride={this.props.timeRangeForSuggestionsOverride} + <EuiFormRow fullWidth - /> + label={this.props.intl.formatMessage({ + id: 'unifiedSearch.filter.filterEditor.valueInputLabel', + defaultMessage: 'Value', + })} + isInvalid={isInvalid} + error={errorMessage} + > + <PhraseValueInput + indexPattern={indexPattern} + field={this.state.selectedField} + value={this.state.params} + onChange={this.onParamsChange} + data-test-subj="phraseValueInput" + timeRangeForSuggestionsOverride={this.props.timeRangeForSuggestionsOverride} + fullWidth + /> + </EuiFormRow> ); case 'phrases': return ( - <PhrasesValuesInput - indexPattern={indexPattern} - field={this.state.selectedField} - values={this.state.params} - onChange={this.onParamsChange} - onParamsUpdate={this.onParamsUpdate} - timeRangeForSuggestionsOverride={this.props.timeRangeForSuggestionsOverride} + <EuiFormRow fullWidth - /> + label={this.props.intl.formatMessage({ + id: 'unifiedSearch.filter.filterEditor.valuesSelectLabel', + defaultMessage: 'Values', + })} + > + <PhrasesValuesInput + indexPattern={indexPattern} + field={this.state.selectedField} + values={this.state.params} + onChange={this.onParamsChange} + onParamsUpdate={this.onParamsUpdate} + timeRangeForSuggestionsOverride={this.props.timeRangeForSuggestionsOverride} + fullWidth + /> + </EuiFormRow> ); case 'range': return ( diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/index.ts b/src/plugins/unified_search/public/filter_bar/filter_editor/index.ts new file mode 100644 index 00000000000000..70b448a80dc33c --- /dev/null +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/index.ts @@ -0,0 +1,41 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { Operator } from './lib'; + +export { + getFieldFromFilter, + getOperatorFromFilter, + getFilterableFields, + getOperatorOptions, + validateParams, + isFilterValid, + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + isBetweenOperator, + isNotBetweenOperator, + existsOperator, + doesNotExistOperator, + FILTER_OPERATORS, +} from './lib'; + +export type { GenericComboBoxProps } from './generic_combo_box'; +export type { PhraseSuggestorProps } from './phrase_suggestor'; +export type { PhrasesSuggestorProps } from './phrases_values_input'; + +export { GenericComboBox } from './generic_combo_box'; +export { PhraseSuggestor } from './phrase_suggestor'; +export { PhrasesValuesInput } from './phrases_values_input'; +export { PhraseValueInput } from './phrase_value_input'; +export { RangeValueInput, isRangeParams } from './range_value_input'; +export { ValueInputType } from './value_input_type'; + +export { FilterEditor } from './filter_editor'; +export type { FilterEditorProps } from './filter_editor'; diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_editor_utils.ts b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_editor_utils.ts index 0863d10fe0c104..b59ddcc424ff88 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_editor_utils.ts +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_editor_utils.ts @@ -37,7 +37,7 @@ export function getOperatorOptions(field: DataViewField) { } export function validateParams(params: any, field: DataViewField) { - switch (field.type) { + switch (field?.type) { case 'date': const moment = typeof params === 'string' ? dateMath.parse(params) : null; return Boolean(typeof params === 'string' && moment && moment.isValid()); diff --git a/src/plugins/unified_search/public/utils/helpers.test.ts b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.test.ts similarity index 100% rename from src/plugins/unified_search/public/utils/helpers.test.ts rename to src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.test.ts diff --git a/src/plugins/unified_search/public/utils/helpers.ts b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.ts similarity index 92% rename from src/plugins/unified_search/public/utils/helpers.ts rename to src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.ts index 6f0a605fa0e142..c0246168671f05 100644 --- a/src/plugins/unified_search/public/utils/helpers.ts +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/helpers.ts @@ -10,13 +10,13 @@ import type { DataViewField } from '@kbn/data-views-plugin/common'; import { i18n } from '@kbn/i18n'; import { KBN_FIELD_TYPES } from '@kbn/data-plugin/public'; import { isEmpty } from 'lodash'; -import { validateParams } from '../filter_bar/filter_editor/lib/filter_editor_utils'; +import { validateParams } from './filter_editor_utils'; export const getFieldValidityAndErrorMessage = ( field: DataViewField, value?: string | undefined ): { isInvalid: boolean; errorMessage?: string } => { - const type = field.type; + const type = field?.type; switch (type) { case KBN_FIELD_TYPES.DATE: case KBN_FIELD_TYPES.DATE_RANGE: diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/index.ts b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/index.ts new file mode 100644 index 00000000000000..8ae6e6bd256078 --- /dev/null +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/lib/index.ts @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { getFieldValidityAndErrorMessage } from './helpers'; +export type { Operator } from './filter_operators'; +export { + isOperator, + isNotOperator, + isOneOfOperator, + isNotOneOfOperator, + isBetweenOperator, + isNotBetweenOperator, + existsOperator, + doesNotExistOperator, + FILTER_OPERATORS, +} from './filter_operators'; +export { + getFieldFromFilter, + getOperatorFromFilter, + getFilterableFields, + getOperatorOptions, + validateParams, + isFilterValid, +} from './filter_editor_utils'; diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_suggestor.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_suggestor.tsx index dc987421e26616..ac5af32203c919 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_suggestor.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_suggestor.tsx @@ -10,13 +10,12 @@ import React from 'react'; import { withKibana, KibanaReactContextValue } from '@kbn/kibana-react-plugin/public'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import { debounce } from 'lodash'; -import { getAutocomplete } from '../../services'; +import { IUnifiedSearchPluginServices } from '../../types'; export interface PhraseSuggestorProps { - kibana: KibanaReactContextValue<IDataPluginServices>; + kibana: KibanaReactContextValue<IUnifiedSearchPluginServices>; indexPattern: DataView; field: DataViewField; timeRangeForSuggestionsOverride?: boolean; @@ -80,7 +79,7 @@ export class PhraseSuggestorUI<T extends PhraseSuggestorProps> extends React.Com return; } this.setState({ isLoading: true }); - const suggestions = await getAutocomplete().getValueSuggestions({ + const suggestions = await this.services.unifiedSearch.autocomplete.getValueSuggestions({ indexPattern, field, query, diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx index c0fe3dc4970255..210b201ec4c683 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/phrase_value_input.tsx @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { EuiFormRow } from '@elastic/eui'; import { InjectedIntl, injectI18n } from '@kbn/i18n-react'; import { uniq } from 'lodash'; import React from 'react'; @@ -14,36 +13,27 @@ import { withKibana } from '@kbn/kibana-react-plugin/public'; import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box'; import { PhraseSuggestorUI, PhraseSuggestorProps } from './phrase_suggestor'; import { ValueInputType } from './value_input_type'; -import { getFieldValidityAndErrorMessage } from '../../utils/helpers'; -interface Props extends PhraseSuggestorProps { +interface PhraseValueInputProps extends PhraseSuggestorProps { value?: string; onChange: (value: string | number | boolean) => void; intl: InjectedIntl; fullWidth?: boolean; + compressed?: boolean; + disabled?: boolean; + isInvalid?: boolean; } -class PhraseValueInputUI extends PhraseSuggestorUI<Props> { +class PhraseValueInputUI extends PhraseSuggestorUI<PhraseValueInputProps> { public render() { - const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage( - this.props.field, - this.props.value - ); - return ( - <EuiFormRow - fullWidth={this.props.fullWidth} - label={this.props.intl.formatMessage({ - id: 'unifiedSearch.filter.filterEditor.valueInputLabel', - defaultMessage: 'Value', - })} - isInvalid={isInvalid} - error={errorMessage} - > + <> {this.isSuggestingValues() ? ( this.renderWithSuggestions() ) : ( <ValueInputType + disabled={this.props.disabled} + compressed={this.props.compressed} fullWidth={this.props.fullWidth} placeholder={this.props.intl.formatMessage({ id: 'unifiedSearch.filter.filterEditor.valueInputPlaceholder', @@ -52,10 +42,10 @@ class PhraseValueInputUI extends PhraseSuggestorUI<Props> { value={this.props.value} onChange={this.props.onChange} field={this.props.field} - isInvalid={isInvalid} + isInvalid={this.props.isInvalid} /> )} - </EuiFormRow> + </> ); } @@ -67,7 +57,9 @@ class PhraseValueInputUI extends PhraseSuggestorUI<Props> { const options = value ? uniq([valueAsStr, ...suggestions]) : suggestions; return ( <StringComboBox + isDisabled={this.props.disabled} fullWidth={fullWidth} + compressed={this.props.compressed} placeholder={intl.formatMessage({ id: 'unifiedSearch.filter.filterEditor.valueSelectPlaceholder', defaultMessage: 'Select a value', diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx index aa819007001a2c..456aa47aeab40f 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/phrases_values_input.tsx @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { EuiFormRow } from '@elastic/eui'; import { InjectedIntl, injectI18n } from '@kbn/i18n-react'; import { uniq } from 'lodash'; import React from 'react'; @@ -14,46 +13,40 @@ import { withKibana } from '@kbn/kibana-react-plugin/public'; import { GenericComboBox, GenericComboBoxProps } from './generic_combo_box'; import { PhraseSuggestorUI, PhraseSuggestorProps } from './phrase_suggestor'; -interface Props extends PhraseSuggestorProps { +export interface PhrasesSuggestorProps extends PhraseSuggestorProps { values?: string[]; onChange: (values: string[]) => void; onParamsUpdate: (value: string) => void; intl: InjectedIntl; fullWidth?: boolean; + compressed?: boolean; } -class PhrasesValuesInputUI extends PhraseSuggestorUI<Props> { +class PhrasesValuesInputUI extends PhraseSuggestorUI<PhrasesSuggestorProps> { public render() { const { suggestions } = this.state; - const { values, intl, onChange, fullWidth, onParamsUpdate } = this.props; + const { values, intl, onChange, fullWidth, onParamsUpdate, compressed } = this.props; const options = values ? uniq([...values, ...suggestions]) : suggestions; return ( - <EuiFormRow + <StringComboBox fullWidth={fullWidth} - label={intl.formatMessage({ - id: 'unifiedSearch.filter.filterEditor.valuesSelectLabel', - defaultMessage: 'Values', + compressed={compressed} + placeholder={intl.formatMessage({ + id: 'unifiedSearch.filter.filterEditor.valuesSelectPlaceholder', + defaultMessage: 'Select values', })} - > - <StringComboBox - fullWidth={fullWidth} - placeholder={intl.formatMessage({ - id: 'unifiedSearch.filter.filterEditor.valuesSelectPlaceholder', - defaultMessage: 'Select values', - })} - delimiter="," - options={options} - getLabel={(option) => option} - selectedOptions={values || []} - onSearchChange={this.onSearchChange} - onCreateOption={(option: string) => { - onParamsUpdate(option.trim()); - }} - onChange={onChange} - isClearable={false} - data-test-subj="filterParamsComboBox phrasesParamsComboxBox" - /> - </EuiFormRow> + delimiter="," + options={options} + getLabel={(option) => option} + selectedOptions={values || []} + onSearchChange={this.onSearchChange} + onCreateOption={(option: string) => { + onParamsUpdate(option.trim()); + }} + onChange={onChange} + isClearable={false} + data-test-subj="filterParamsComboBox phrasesParamsComboxBox" + /> ); } } diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx index 26a25886ac8666..27a1d9db7739d2 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/range_value_input.tsx @@ -28,6 +28,11 @@ interface Props { onChange: (params: RangeParamsPartial) => void; intl: InjectedIntl; fullWidth?: boolean; + compressed?: boolean; +} + +export function isRangeParams(params: any): params is RangeParams { + return Boolean(params && 'from' in params && 'to' in params); } function RangeValueInputUI(props: Props) { @@ -68,6 +73,7 @@ function RangeValueInputUI(props: Props) { startControl={ <ValueInputType controlOnly + compressed={props.compressed} field={props.field} value={props.value ? props.value.from : undefined} onChange={onFromChange} @@ -83,6 +89,7 @@ function RangeValueInputUI(props: Props) { endControl={ <ValueInputType controlOnly + compressed={props.compressed} field={props.field} value={props.value ? props.value.to : undefined} onChange={onToChange} diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/value_input_type.tsx b/src/plugins/unified_search/public/filter_bar/filter_editor/value_input_type.tsx index a87888ed85c93b..d250f5be388d9d 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/value_input_type.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_editor/value_input_type.tsx @@ -24,6 +24,8 @@ interface Props { className?: string; fullWidth?: boolean; isInvalid?: boolean; + compressed?: boolean; + disabled?: boolean; } class ValueInputTypeUI extends Component<Props> { @@ -37,12 +39,14 @@ class ValueInputTypeUI extends Component<Props> { public render() { const value = this.props.value; - const type = this.props.field.type; + const type = this.props.field?.type ?? 'string'; let inputElement: React.ReactNode; switch (type) { case 'string': inputElement = ( <EuiFieldText + compressed={this.props.compressed} + disabled={this.props.disabled} fullWidth={this.props.fullWidth} placeholder={this.props.placeholder} value={value} @@ -57,6 +61,8 @@ class ValueInputTypeUI extends Component<Props> { case 'number_range': inputElement = ( <EuiFieldNumber + compressed={this.props.compressed} + disabled={this.props.disabled} fullWidth={this.props.fullWidth} placeholder={this.props.placeholder} value={this.getValueForNumberField(value)} @@ -70,6 +76,8 @@ class ValueInputTypeUI extends Component<Props> { case 'date_range': inputElement = ( <EuiFieldText + compressed={this.props.compressed} + disabled={this.props.disabled} fullWidth={this.props.fullWidth} placeholder={this.props.placeholder} value={value} @@ -86,12 +94,14 @@ class ValueInputTypeUI extends Component<Props> { inputElement = ( <EuiFieldText fullWidth={this.props.fullWidth} + disabled={this.props.disabled} placeholder={this.props.placeholder} value={value} onChange={this.onChange} isInvalid={!isEmpty(value) && !validateParams(value, this.props.field)} controlOnly={this.props.controlOnly} className={this.props.className} + compressed={this.props.compressed} /> ); break; @@ -119,6 +129,7 @@ class ValueInputTypeUI extends Component<Props> { onChange={this.onBoolChange} className={this.props.className} fullWidth={this.props.fullWidth} + compressed={this.props.compressed} /> ); break; diff --git a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx index abacffe4a46a9e..3692b19f7e4400 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx @@ -27,7 +27,7 @@ import { getDisplayValueFromFilter, getFieldDisplayValueFromFilter, } from '@kbn/data-plugin/public'; -import { FilterEditor } from '../filter_editor'; +import { FilterEditor } from '../filter_editor/filter_editor'; import { FilterView } from '../filter_view'; import { getIndexPatterns } from '../../services'; import { FilterPanelOption } from '../../types'; diff --git a/src/plugins/unified_search/public/filter_bar/filter_item/filter_items.tsx b/src/plugins/unified_search/public/filter_bar/filter_item/filter_items.tsx index 4c29c4284860d3..c46a4973e2457e 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_item/filter_items.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_item/filter_items.tsx @@ -11,11 +11,11 @@ import { css } from '@emotion/react'; import { EuiFlexItem } from '@elastic/eui'; import { InjectedIntl, injectI18n } from '@kbn/i18n-react'; import type { Filter } from '@kbn/es-query'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import { METRIC_TYPE } from '@kbn/analytics'; import { DataView } from '@kbn/data-views-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { FilterItem, FilterItemProps } from './filter_item'; +import type { IUnifiedSearchPluginServices } from '../../types'; /** * Properties for the filter items component, which will render a single filter pill for every filter that is sent in @@ -41,7 +41,7 @@ export interface FilterItemsProps { const FilterItemsUI = React.memo(function FilterItemsUI(props: FilterItemsProps) { const groupRef = useRef<HTMLDivElement>(null); - const kibana = useKibana<IDataPluginServices>(); + const kibana = useKibana<IUnifiedSearchPluginServices>(); const { appName, usageCollection, uiSettings } = kibana.services; const { readOnly = false } = props; diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/__snapshots__/filter_label.test.tsx.snap b/src/plugins/unified_search/public/filter_bar/filter_label/__snapshots__/filter_label.test.tsx.snap similarity index 100% rename from src/plugins/unified_search/public/filter_bar/filter_editor/lib/__snapshots__/filter_label.test.tsx.snap rename to src/plugins/unified_search/public/filter_bar/filter_label/__snapshots__/filter_label.test.tsx.snap diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_label.test.tsx b/src/plugins/unified_search/public/filter_bar/filter_label/filter_label.test.tsx similarity index 100% rename from src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_label.test.tsx rename to src/plugins/unified_search/public/filter_bar/filter_label/filter_label.test.tsx diff --git a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_label.tsx b/src/plugins/unified_search/public/filter_bar/filter_label/filter_label.tsx similarity index 94% rename from src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_label.tsx rename to src/plugins/unified_search/public/filter_bar/filter_label/filter_label.tsx index 35c05316465f80..261a2a6e7afb20 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_editor/lib/filter_label.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_label/filter_label.tsx @@ -10,8 +10,8 @@ import React, { Fragment } from 'react'; import { EuiTextColor } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { Filter, FILTERS } from '@kbn/es-query'; -import { existsOperator, isOneOfOperator } from './filter_operators'; -import type { FilterLabelStatus } from '../../filter_item/filter_item'; +import type { FilterLabelStatus } from '../filter_item/filter_item'; +import { existsOperator, isOneOfOperator } from '../filter_editor'; export interface FilterLabelProps { filter: Filter; diff --git a/src/plugins/unified_search/public/filter_bar/index.tsx b/src/plugins/unified_search/public/filter_bar/index.tsx index a70b6b93de5dd1..a0fee65518fa85 100644 --- a/src/plugins/unified_search/public/filter_bar/index.tsx +++ b/src/plugins/unified_search/public/filter_bar/index.tsx @@ -29,7 +29,7 @@ export const FilterItems = (props: React.ComponentProps<typeof LazyFilterItems>) </React.Suspense> ); -const LazyFilterLabel = React.lazy(() => import('./filter_editor/lib/filter_label')); +const LazyFilterLabel = React.lazy(() => import('./filter_label/filter_label')); /** * Renders the label for a single filter pill */ diff --git a/src/plugins/unified_search/public/filters_builder/__mock__/filters.ts b/src/plugins/unified_search/public/filters_builder/__mock__/filters.ts new file mode 100644 index 00000000000000..03d5b4333cff46 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/__mock__/filters.ts @@ -0,0 +1,630 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Filter } from '@kbn/es-query'; + +export const getFiltersMock = () => + [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 1", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 1", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + type: 'OR', + params: [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 2", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 2", + }, + }, + $state: { + store: 'appState', + }, + }, + [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 3", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 3", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 4", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 4", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 5", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 5", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 6", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 6", + }, + }, + $state: { + store: 'appState', + }, + }, + ] as Filter[]; + +export const getFiltersMockOrHide = () => + [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 1", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 1", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 2", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 2", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 3", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 3", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 4", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 4", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 5", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 5", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 6", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 6", + }, + }, + $state: { + store: 'appState', + }, + }, + ] as Filter[]; + +export const getDataThatNeedsNormalized = () => + [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 1", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 1", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + type: 'OR', + params: [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 2", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 2", + }, + }, + $state: { + store: 'appState', + }, + }, + [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 3", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 3", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 5", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 5", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 6", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 6", + }, + }, + $state: { + store: 'appState', + }, + }, + ] as Filter[]; + +export const getDataAfterNormalized = () => + [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 1", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 1", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + type: 'OR', + params: [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 2", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 2", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 3", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 3", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 5", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 5", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 6", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 6", + }, + }, + $state: { + store: 'appState', + }, + }, + ] as Filter[]; + +export const getDataThatNeedNotNormalized = () => + [ + { + meta: { + type: 'OR', + params: [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 2", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 2", + }, + }, + $state: { + store: 'appState', + }, + }, + [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 3", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 3", + }, + }, + $state: { + store: 'appState', + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 4", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 4", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 5", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 5", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + }, + }, + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories 6", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories 6", + }, + }, + $state: { + store: 'appState', + }, + }, + ] as Filter[]; diff --git a/src/plugins/unified_search/public/filters_builder/__stories__/filter_builder.stories.tsx b/src/plugins/unified_search/public/filters_builder/__stories__/filter_builder.stories.tsx new file mode 100644 index 00000000000000..aebf85440dfe47 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/__stories__/filter_builder.stories.tsx @@ -0,0 +1,188 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { FC } from 'react'; +import { ComponentStory } from '@storybook/react'; +import { I18nProvider } from '@kbn/i18n-react'; +import { EuiForm } from '@elastic/eui'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import { action } from '@storybook/addon-actions'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import type { Filter } from '@kbn/es-query'; +import { getFiltersMock, getFiltersMockOrHide } from '../__mock__/filters'; +import FiltersBuilder, { FiltersBuilderProps } from '../filters_builder'; + +export default { + title: 'Filters Builder', + component: FiltersBuilder, + decorators: [(story: Function) => <EuiForm>{story()}</EuiForm>], +}; + +const Template: ComponentStory<FC<FiltersBuilderProps>> = (args) => <FiltersBuilder {...args} />; + +export const Default = Template.bind({}); + +Default.decorators = [ + (Story) => ( + <I18nProvider> + <KibanaContextProvider services={services}> + <Story /> + </KibanaContextProvider> + </I18nProvider> + ), +]; + +const mockedDataView = { + id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + title: 'logstash-*', + fields: [ + { + name: 'category.keyword', + type: 'string', + esTypes: ['integer'], + aggregatable: true, + filterable: true, + searchable: true, + }, + ], +} as DataView; + +const filters = getFiltersMock(); + +Default.args = { + filters, + dataView: mockedDataView, + onChange: (f: Filter[]) => {}, + hideOr: false, +}; + +export const withoutOR = Template.bind({}); +withoutOR.args = { ...Default.args, filters: getFiltersMockOrHide(), hideOr: true }; + +withoutOR.decorators = [ + (Story) => ( + <I18nProvider> + <KibanaContextProvider services={services}> + <Story /> + </KibanaContextProvider> + </I18nProvider> + ), +]; + +const createMockWebStorage = () => ({ + clear: action('clear'), + getItem: action('getItem'), + key: action('key'), + removeItem: action('removeItem'), + setItem: action('setItem'), + length: 0, +}); + +const createMockStorage = () => ({ + storage: createMockWebStorage(), + set: action('set'), + remove: action('remove'), + clear: action('clear'), + get: () => true, +}); + +const services = { + uiSettings: { + get: () => true, + }, + savedObjects: action('savedObjects'), + notifications: action('notifications'), + http: { + basePath: { + prepend: () => 'http://test', + }, + }, + docLinks: { + links: { + query: { + kueryQuerySyntax: '', + }, + }, + }, + storage: createMockStorage(), + data: { + query: { + savedQueries: { + findSavedQueries: () => + Promise.resolve({ + queries: [ + { + id: 'testwewe', + attributes: { + title: 'Saved query 1', + description: '', + query: { + query: 'category.keyword : "Men\'s Shoes" ', + language: 'kuery', + }, + filters: [], + }, + }, + { + id: '0173d0d0-b19a-11ec-8323-837d6b231b82', + attributes: { + title: 'test', + description: '', + query: { + query: '', + language: 'kuery', + }, + filters: [ + { + meta: { + index: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + alias: null, + negate: false, + disabled: false, + type: 'phrase', + key: 'category.keyword', + params: { + query: "Men's Accessories", + }, + }, + query: { + match_phrase: { + 'category.keyword': "Men's Accessories", + }, + }, + $state: { + store: 'appState', + }, + }, + ], + }, + }, + ], + }), + }, + }, + dataViews: { + getIdsWithTitle: () => [ + { id: '8a0b7cd0-b0c4-11ec-92b2-73d62e0d28a9', title: 'logstash-*' }, + { id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', title: 'test-*' }, + ], + }, + }, + unifiedSearch: { + autocomplete: { + hasQuerySuggestions: () => Promise.resolve(false), + getQuerySuggestions: () => [], + getValueSuggestions: () => + new Promise((resolve) => { + setTimeout(() => { + resolve([]); + }, 300); + }), + }, + }, +}; diff --git a/src/plugins/unified_search/public/filters_builder/assets/add.svg b/src/plugins/unified_search/public/filters_builder/assets/add.svg new file mode 100644 index 00000000000000..cfc9907424f623 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/assets/add.svg @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="27px" height="40px" viewBox="0 0 27 40" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>add + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/plugins/unified_search/public/filters_builder/assets/or.svg b/src/plugins/unified_search/public/filters_builder/assets/or.svg new file mode 100644 index 00000000000000..d0be3ff2e77fe4 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/assets/or.svg @@ -0,0 +1,33 @@ + + + or + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder.tsx b/src/plugins/unified_search/public/filters_builder/filters_builder.tsx new file mode 100644 index 00000000000000..c7251bb78518c1 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder.tsx @@ -0,0 +1,126 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useEffect, useReducer, useCallback, useState, useMemo } from 'react'; +import { EuiDragDropContext, DragDropContextProps, useEuiPaddingSize } from '@elastic/eui'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { Filter } from '@kbn/es-query'; +import { css } from '@emotion/css'; +import { FiltersBuilderContextType } from './filters_builder_context'; +import { ConditionTypes } from '../utils'; +import { FilterGroup } from './filters_builder_filter_group'; +import { FiltersBuilderReducer } from './filters_builder_reducer'; + +export interface FiltersBuilderProps { + filters: Filter[]; + dataView: DataView; + onChange: (filters: Filter[]) => void; + timeRangeForSuggestionsOverride?: boolean; + maxDepth?: number; + hideOr?: boolean; +} + +const rootLevelConditionType = ConditionTypes.AND; +const DEFAULT_MAX_DEPTH = 10; + +function FiltersBuilder({ + onChange, + dataView, + filters, + timeRangeForSuggestionsOverride, + maxDepth = DEFAULT_MAX_DEPTH, + hideOr = false, +}: FiltersBuilderProps) { + const [state, dispatch] = useReducer(FiltersBuilderReducer, { filters }); + const [dropTarget, setDropTarget] = useState(''); + const mPaddingSize = useEuiPaddingSize('m'); + + const filtersBuilderStyles = useMemo( + () => css` + .filter-builder__panel { + &.filter-builder__panel-nested { + padding: ${mPaddingSize} 0; + } + } + + .filter-builder__item { + &.filter-builder__item-nested { + padding: 0 ${mPaddingSize}; + } + } + `, + [mPaddingSize] + ); + + useEffect(() => { + if (state.filters !== filters) { + onChange(state.filters); + } + }, [filters, onChange, state.filters]); + + const handleMoveFilter = useCallback( + (pathFrom: string, pathTo: string, conditionalType: ConditionTypes) => { + if (pathFrom === pathTo) { + return null; + } + + dispatch({ + type: 'moveFilter', + payload: { + pathFrom, + pathTo, + conditionalType, + }, + }); + }, + [] + ); + + const onDragEnd: DragDropContextProps['onDragEnd'] = ({ combine, source, destination }) => { + if (source && destination) { + handleMoveFilter(source.droppableId, destination.droppableId, ConditionTypes.AND); + } + + if (source && combine) { + handleMoveFilter(source.droppableId, combine.droppableId, ConditionTypes.OR); + } + setDropTarget(''); + }; + + const onDragActive: DragDropContextProps['onDragUpdate'] = ({ destination, combine }) => { + if (destination) { + setDropTarget(destination.droppableId); + } + + if (combine) { + setDropTarget(combine.droppableId); + } + }; + + return ( +
+ + + + + +
+ ); +} + +// React.lazy support +// eslint-disable-next-line import/no-default-export +export default FiltersBuilder; diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_context.ts b/src/plugins/unified_search/public/filters_builder/filters_builder_context.ts new file mode 100644 index 00000000000000..8dfab23f978873 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_context.ts @@ -0,0 +1,26 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { Dispatch } from 'react'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { FiltersBuilderActions } from './filters_builder_reducer'; + +interface FiltersBuilderContextType { + dataView: DataView; + dispatch: Dispatch; + globalParams: { + maxDepth: number; + hideOr: boolean; + }; + dropTarget: string; + timeRangeForSuggestionsOverride?: boolean; +} + +export const FiltersBuilderContextType = React.createContext( + {} as FiltersBuilderContextType +); diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_filter_group.tsx b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_group.tsx new file mode 100644 index 00000000000000..adb77f7b9d2eac --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_group.tsx @@ -0,0 +1,149 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useContext, useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiText, + useEuiBackgroundColor, + useEuiPaddingSize, +} from '@elastic/eui'; +import { Filter } from '@kbn/es-query'; +import { css, cx } from '@emotion/css'; +import type { Path } from './filters_builder_types'; +import { ConditionTypes, getConditionalOperationType } from '../utils'; +import { FilterItem } from './filters_builder_filter_item'; +import { FiltersBuilderContextType } from './filters_builder_context'; +import { getPathInArray } from './filters_builder_utils'; + +export interface FilterGroupProps { + filters: Filter[]; + conditionType: ConditionTypes; + path: Path; + + /** @internal used for recursive rendering **/ + renderedLevel?: number; + reverseBackground?: boolean; +} + +/** @internal **/ +const Delimiter = ({ + color, + conditionType, +}: { + color: 'subdued' | 'plain'; + conditionType: ConditionTypes; +}) => { + const xsPadding = useEuiPaddingSize('xs'); + const mPadding = useEuiPaddingSize('m'); + const backgroundColor = useEuiBackgroundColor(color); + + const delimiterStyles = useMemo( + () => css` + position: relative; + + .filter-builder__delimiter_text { + position: absolute; + display: block; + padding: ${xsPadding}; + top: 0; + left: ${mPadding}; + background: ${backgroundColor}; + } + `, + [backgroundColor, mPadding, xsPadding] + ); + + return ( +
+ + + {i18n.translate('unifiedSearch.filter.filtersBuilder.delimiterLabel', { + defaultMessage: '{conditionType}', + values: { + conditionType, + }, + })} + +
+ ); +}; + +export const FilterGroup = ({ + filters, + conditionType, + path, + reverseBackground = false, + renderedLevel = 0, +}: FilterGroupProps) => { + const { + globalParams: { maxDepth, hideOr }, + } = useContext(FiltersBuilderContextType); + + const pathInArray = getPathInArray(path); + const isDepthReached = maxDepth <= pathInArray.length; + const orDisabled = hideOr || (isDepthReached && conditionType === ConditionTypes.AND); + const andDisabled = isDepthReached && conditionType === ConditionTypes.OR; + const removeDisabled = pathInArray.length <= 1 && filters.length === 1; + const shouldNormalizeFirstLevel = + !path && filters.length === 1 && getConditionalOperationType(filters[0]); + + if (shouldNormalizeFirstLevel) { + reverseBackground = true; + renderedLevel -= 1; + } + + const color = reverseBackground ? 'plain' : 'subdued'; + + const renderedFilters = filters.map((filter, index, acc) => ( + + + + + + {conditionType && index + 1 < acc.length ? ( + + {conditionType === ConditionTypes.OR && ( + + )} + + ) : null} + + )); + + return shouldNormalizeFirstLevel ? ( + <>{renderedFilters} + ) : ( + 0, + })} + > + {renderedFilters} + + ); +}; diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item.tsx b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item.tsx new file mode 100644 index 00000000000000..30b73d397b674f --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item.tsx @@ -0,0 +1,317 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback, useContext, useMemo } from 'react'; +import { + EuiButtonIcon, + EuiDraggable, + EuiDroppable, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiIcon, + EuiPanel, + useEuiTheme, +} from '@elastic/eui'; +import { buildEmptyFilter, FieldFilter, Filter, getFilterParams } from '@kbn/es-query'; +import { DataViewField } from '@kbn/data-views-plugin/common'; +import { i18n } from '@kbn/i18n'; +import { cx, css } from '@emotion/css'; + +import add from '../assets/add.svg'; +import or from '../assets/or.svg'; + +import { FieldInput } from './filters_builder_filter_item_field_input'; +import { OperatorInput } from './filters_builder_filter_item_operator_input'; +import { ParamsEditor } from './filters_builder_filter_item_params_editor'; +import { ConditionTypes, getConditionalOperationType } from '../../utils'; +import { FiltersBuilderContextType } from '../filters_builder_context'; +import { FilterGroup } from '../filters_builder_filter_group'; +import type { Path } from '../filters_builder_types'; +import { getFieldFromFilter, getOperatorFromFilter } from '../../filter_bar/filter_editor'; +import { Operator } from '../../filter_bar/filter_editor'; + +export interface FilterItemProps { + path: Path; + filter: Filter; + disableOr: boolean; + disableAnd: boolean; + disableRemove: boolean; + color: 'plain' | 'subdued'; + index: number; + + /** @internal used for recursive rendering **/ + renderedLevel: number; + reverseBackground: boolean; +} + +const cursorAddStyles = css` + cursor: url(${add}), auto; +`; + +const cursorOrStyles = css` + cursor: url(${or}), auto; +`; + +export function FilterItem({ + filter, + path, + reverseBackground, + disableOr, + disableAnd, + disableRemove, + color, + index, + renderedLevel, +}: FilterItemProps) { + const { + dispatch, + dataView, + dropTarget, + globalParams: { hideOr }, + timeRangeForSuggestionsOverride, + } = useContext(FiltersBuilderContextType); + const conditionalOperationType = getConditionalOperationType(filter); + const { euiTheme } = useEuiTheme(); + + const grabIconStyles = useMemo( + () => css` + margin: 0 ${euiTheme.size.xxs}; + `, + [euiTheme.size.xxs] + ); + + let field: DataViewField | undefined; + let operator: Operator | undefined; + let params: Filter['meta']['params'] | undefined; + + if (!conditionalOperationType) { + field = getFieldFromFilter(filter as FieldFilter, dataView); + operator = getOperatorFromFilter(filter); + params = getFilterParams(filter); + } + + const onHandleField = useCallback( + (selectedField: DataViewField) => { + dispatch({ + type: 'updateFilter', + payload: { path, field: selectedField }, + }); + }, + [dispatch, path] + ); + + const onHandleOperator = useCallback( + (selectedOperator: Operator) => { + dispatch({ + type: 'updateFilter', + payload: { path, field, operator: selectedOperator }, + }); + }, + [dispatch, path, field] + ); + + const onHandleParamsChange = useCallback( + (selectedParams: string) => { + dispatch({ + type: 'updateFilter', + payload: { path, field, operator, params: selectedParams }, + }); + }, + [dispatch, path, field, operator] + ); + + const onHandleParamsUpdate = useCallback( + (value: Filter['meta']['params']) => { + dispatch({ + type: 'updateFilter', + payload: { path, params: [value, ...(params || [])] }, + }); + }, + [dispatch, path, params] + ); + + const onRemoveFilter = useCallback(() => { + dispatch({ + type: 'removeFilter', + payload: { + path, + }, + }); + }, [dispatch, path]); + + const onAddFilter = useCallback( + (conditionalType: ConditionTypes) => { + dispatch({ + type: 'addFilter', + payload: { + path, + filter: buildEmptyFilter(false, dataView.id), + conditionalType, + }, + }); + }, + [dispatch, dataView.id, path] + ); + + const onAddButtonClick = useCallback(() => onAddFilter(ConditionTypes.AND), [onAddFilter]); + const onOrButtonClick = useCallback(() => onAddFilter(ConditionTypes.OR), [onAddFilter]); + + if (!dataView) { + return null; + } + + return ( +
0, + })} + > + {conditionalOperationType ? ( + + ) : ( + + + {(provided) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {!hideOr ? ( + + + + ) : null} + + + + + + + + + + )} + + + )} +
+ ); +} diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_field_input.tsx b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_field_input.tsx new file mode 100644 index 00000000000000..3ff823a09cb5de --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_field_input.tsx @@ -0,0 +1,51 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; +import type { DataView, DataViewField } from '@kbn/data-views-plugin/common'; +import { useGeneratedHtmlId } from '@elastic/eui'; +import { getFilterableFields, GenericComboBox } from '../../filter_bar/filter_editor'; + +interface FieldInputProps { + dataView: DataView; + onHandleField: (field: DataViewField) => void; + field?: DataViewField; +} + +export function FieldInput({ field, dataView, onHandleField }: FieldInputProps) { + const fields = dataView ? getFilterableFields(dataView) : []; + const id = useGeneratedHtmlId({ prefix: 'fieldInput' }); + + const onFieldChange = useCallback( + ([selectedField]: DataViewField[]) => { + onHandleField(selectedField); + }, + [onHandleField] + ); + + const getLabel = useCallback((view: DataViewField) => view.customLabel || view.name, []); + + return ( + + ); +} diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_operator_input.tsx b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_operator_input.tsx new file mode 100644 index 00000000000000..2f73df35962127 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_operator_input.tsx @@ -0,0 +1,61 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; +import type { DataViewField } from '@kbn/data-views-plugin/common'; +import type { Operator } from '../../filter_bar/filter_editor'; +import { getOperatorOptions, GenericComboBox } from '../../filter_bar/filter_editor'; + +interface OperatorInputProps { + field: DataViewField | undefined; + operator: Operator | undefined; + params: TParams; + onHandleOperator: (operator: Operator, params?: TParams) => void; +} + +export function OperatorInput({ + field, + operator, + params, + onHandleOperator, +}: OperatorInputProps) { + const operators = field ? getOperatorOptions(field) : []; + + const onOperatorChange = useCallback( + ([selectedOperator]: Operator[]) => { + const selectedParams = selectedOperator === operator ? params : undefined; + + onHandleOperator(selectedOperator, selectedParams); + }, + [onHandleOperator, operator, params] + ); + + return ( + message} + onChange={onOperatorChange} + singleSelection={{ asPlainText: true }} + isClearable={false} + /> + ); +} diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_params_editor.tsx b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_params_editor.tsx new file mode 100644 index 00000000000000..17c571ac7ed39a --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/filters_builder_filter_item_params_editor.tsx @@ -0,0 +1,113 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback } from 'react'; +import { DataView, DataViewField } from '@kbn/data-views-plugin/common'; +import { EuiFormRow } from '@elastic/eui'; +import type { Operator } from '../../filter_bar/filter_editor'; +import { + PhraseValueInput, + PhrasesValuesInput, + RangeValueInput, + isRangeParams, +} from '../../filter_bar/filter_editor'; +import { getFieldValidityAndErrorMessage } from '../../filter_bar/filter_editor/lib'; + +interface ParamsEditorProps { + dataView: DataView; + params: TParams; + onHandleParamsChange: (params: TParams) => void; + onHandleParamsUpdate: (value: TParams) => void; + timeRangeForSuggestionsOverride?: boolean; + field?: DataViewField; + operator?: Operator; +} + +export function ParamsEditor({ + dataView, + field, + operator, + params, + onHandleParamsChange, + onHandleParamsUpdate, + timeRangeForSuggestionsOverride, +}: ParamsEditorProps) { + const onParamsChange = useCallback( + (selectedParams) => { + onHandleParamsChange(selectedParams); + }, + [onHandleParamsChange] + ); + + const onParamsUpdate = useCallback( + (value) => { + onHandleParamsUpdate(value); + }, + [onHandleParamsUpdate] + ); + + const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage( + field!, + typeof params === 'string' ? params : undefined + ); + + switch (operator?.type) { + case 'exists': + return null; + case 'phrase': + return ( + + + + ); + case 'phrases': + return ( + + ); + case 'range': + return ( + + ); + default: + return ( + + ); + } +} diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/index.ts b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/index.ts new file mode 100644 index 00000000000000..07dd57964a13e0 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_filter_item/index.ts @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { FilterItem } from './filters_builder_filter_item'; diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_reducer.ts b/src/plugins/unified_search/public/filters_builder/filters_builder_reducer.ts new file mode 100644 index 00000000000000..3dde3bdddac67b --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_reducer.ts @@ -0,0 +1,99 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Reducer } from 'react'; +import type { Filter } from '@kbn/es-query'; +import type { DataViewField } from '@kbn/data-views-plugin/common'; +import type { Path } from './filters_builder_types'; +import type { ConditionTypes } from '../utils'; +import { addFilter, moveFilter, removeFilter, updateFilter } from './filters_builder_utils'; +import type { Operator } from '../filter_bar/filter_editor'; + +/** @internal **/ +export interface FiltersBuilderState { + filters: Filter[]; +} + +/** @internal **/ +export interface AddFilterPayload { + path: Path; + filter: Filter; + conditionalType: ConditionTypes; +} + +/** @internal **/ +export interface UpdateFilterPayload { + path: string; + field?: DataViewField; + operator?: Operator; + params?: Filter['meta']['params']; +} + +/** @internal **/ +export interface RemoveFilterPayload { + path: Path; +} + +/** @internal **/ +export interface MoveFilterPayload { + pathFrom: Path; + pathTo: Path; + conditionalType: ConditionTypes; +} + +/** @internal **/ +export type FiltersBuilderActions = + | { type: 'addFilter'; payload: AddFilterPayload } + | { type: 'removeFilter'; payload: RemoveFilterPayload } + | { type: 'moveFilter'; payload: MoveFilterPayload } + | { type: 'updateFilter'; payload: UpdateFilterPayload }; + +export const FiltersBuilderReducer: Reducer = ( + state, + action +) => { + switch (action.type) { + case 'addFilter': + return { + filters: addFilter( + state.filters, + action.payload.filter, + action.payload.path, + action.payload.conditionalType + ), + }; + case 'removeFilter': + return { + ...state, + filters: removeFilter(state.filters, action.payload.path), + }; + case 'moveFilter': + return { + ...state, + filters: moveFilter( + state.filters, + action.payload.pathFrom, + action.payload.pathTo, + action.payload.conditionalType + ), + }; + case 'updateFilter': + return { + ...state, + filters: updateFilter( + state.filters, + action.payload.path, + action.payload.field, + action.payload.operator, + action.payload.params + ), + }; + default: + throw new Error('wrong action'); + } +}; diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_types.ts b/src/plugins/unified_search/public/filters_builder/filters_builder_types.ts new file mode 100644 index 00000000000000..24d0b9015aa749 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_types.ts @@ -0,0 +1,10 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** @internal **/ +export type Path = string; diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_utils.test.ts b/src/plugins/unified_search/public/filters_builder/filters_builder_utils.test.ts new file mode 100644 index 00000000000000..517a0cea4cce7a --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_utils.test.ts @@ -0,0 +1,261 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { buildEmptyFilter, Filter } from '@kbn/es-query'; +import { ConditionTypes } from '../utils'; +import { + getFilterByPath, + getPathInArray, + addFilter, + removeFilter, + moveFilter, + normalizeFilters, +} from './filters_builder_utils'; +import type { FilterItem } from '../utils'; +import { getConditionalOperationType } from '../utils'; + +import { + getDataAfterNormalized, + getDataThatNeedNotNormalized, + getDataThatNeedsNormalized, + getFiltersMock, +} from './__mock__/filters'; + +describe('filters_builder_utils', () => { + let filters: Filter[]; + beforeAll(() => { + filters = getFiltersMock(); + }); + + describe('getFilterByPath', () => { + test('should return correct filterByPath', () => { + expect(getFilterByPath(filters, '0')).toMatchInlineSnapshot(` + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + "key": "category.keyword", + "negate": false, + "params": Object { + "query": "Men's Accessories 1", + }, + "type": "phrase", + }, + "query": Object { + "match_phrase": Object { + "category.keyword": "Men's Accessories 1", + }, + }, + } + `); + expect(getFilterByPath(filters, '2')).toMatchInlineSnapshot(` + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + "key": "category.keyword", + "negate": false, + "params": Object { + "query": "Men's Accessories 6", + }, + "type": "phrase", + }, + "query": Object { + "match_phrase": Object { + "category.keyword": "Men's Accessories 6", + }, + }, + } + `); + expect(getFilterByPath(filters, '1.2')).toMatchInlineSnapshot(` + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + "key": "category.keyword", + "negate": false, + "params": Object { + "query": "Men's Accessories 5", + }, + "type": "phrase", + }, + "query": Object { + "match_phrase": Object { + "category.keyword": "Men's Accessories 5", + }, + }, + } + `); + expect(getFilterByPath(filters, '1.1.1')).toMatchInlineSnapshot(` + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + "key": "category.keyword", + "negate": false, + "params": Object { + "query": "Men's Accessories 4", + }, + "type": "phrase", + }, + "query": Object { + "match_phrase": Object { + "category.keyword": "Men's Accessories 4", + }, + }, + } + `); + expect(getFilterByPath(filters, '1.1')).toMatchInlineSnapshot(` + Array [ + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + "key": "category.keyword", + "negate": false, + "params": Object { + "query": "Men's Accessories 3", + }, + "type": "phrase", + }, + "query": Object { + "match_phrase": Object { + "category.keyword": "Men's Accessories 3", + }, + }, + }, + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + "key": "category.keyword", + "negate": false, + "params": Object { + "query": "Men's Accessories 4", + }, + "type": "phrase", + }, + "query": Object { + "match_phrase": Object { + "category.keyword": "Men's Accessories 4", + }, + }, + }, + ] + `); + }); + }); + + describe('getConditionalOperationType', () => { + let filter: Filter; + let filtersWithOrRelationships: FilterItem; + let groupOfFilters: FilterItem; + + beforeAll(() => { + filter = filters[0]; + filtersWithOrRelationships = filters[1]; + groupOfFilters = filters[1].meta.params; + }); + + test('should return correct ConditionalOperationType', () => { + expect(getConditionalOperationType(filter)).toBeUndefined(); + expect(getConditionalOperationType(filtersWithOrRelationships)).toBe(ConditionTypes.OR); + expect(getConditionalOperationType(groupOfFilters)).toBe(ConditionTypes.AND); + }); + }); + + describe('getPathInArray', () => { + test('should return correct path in array from path', () => { + expect(getPathInArray('0')).toStrictEqual([0]); + expect(getPathInArray('1.1')).toStrictEqual([1, 1]); + expect(getPathInArray('1.0.2')).toStrictEqual([1, 0, 2]); + }); + }); + + describe('addFilter', () => { + const emptyFilter = buildEmptyFilter(false); + + test('should add filter into filters after zero element', () => { + const enlargedFilters = addFilter(filters, emptyFilter, '0', ConditionTypes.AND); + expect(getFilterByPath(enlargedFilters, '1')).toMatchInlineSnapshot(` + Object { + "$state": Object { + "store": "appState", + }, + "meta": Object { + "alias": null, + "disabled": false, + "index": undefined, + "negate": false, + }, + } + `); + }); + }); + + describe('removeFilter', () => { + test('should remove filter from filters', () => { + const path = '1.1'; + const filterBeforeRemoved = getFilterByPath(filters, path); + const filtersAfterRemoveFilter = removeFilter(filters, path); + const filterObtainedAfterFilterRemovalFromFilters = getFilterByPath( + filtersAfterRemoveFilter, + path + ); + + expect(filterBeforeRemoved).not.toBe(filterObtainedAfterFilterRemovalFromFilters); + }); + }); + + describe('moveFilter', () => { + test('should move filter from "0" path to "2" path into filters', () => { + const filterBeforeMoving = getFilterByPath(filters, '0'); + const filtersAfterMovingFilter = moveFilter(filters, '0', '2', ConditionTypes.AND); + const filterObtainedAfterFilterMovingFilters = getFilterByPath(filtersAfterMovingFilter, '2'); + expect(filterBeforeMoving).toEqual(filterObtainedAfterFilterMovingFilters); + }); + }); + + describe('normalizeFilters', () => { + test('should normalize filter after removed filter', () => { + const dataNeedsNormalized = getDataThatNeedsNormalized(); + const dataAfterNormalized = getDataAfterNormalized(); + expect(normalizeFilters(dataNeedsNormalized)).toEqual(dataAfterNormalized); + }); + + test('should not normalize filter after removed filter', () => { + const dataNeedNotNormalized = getDataThatNeedNotNormalized(); + const dataAfterNormalized = getDataThatNeedNotNormalized(); + expect(normalizeFilters(dataNeedNotNormalized)).toEqual(dataAfterNormalized); + }); + }); +}); diff --git a/src/plugins/unified_search/public/filters_builder/filters_builder_utils.ts b/src/plugins/unified_search/public/filters_builder/filters_builder_utils.ts new file mode 100644 index 00000000000000..dbbc81824a479f --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/filters_builder_utils.ts @@ -0,0 +1,360 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataViewField } from '@kbn/data-views-plugin/common'; +import type { Filter } from '@kbn/es-query'; +import { cloneDeep } from 'lodash'; +import { ConditionTypes, getConditionalOperationType, isOrFilter, buildOrFilter } from '../utils'; +import type { FilterItem } from '../utils'; +import type { Operator } from '../filter_bar/filter_editor'; + +const PATH_SEPARATOR = '.'; + +/** + * The method returns the filter nesting identification number as an array. + * @param {string} path - variable is used to identify the filter and its nesting in the filter group. + */ +export const getPathInArray = (path: string) => path.split(PATH_SEPARATOR).map((i) => +i); + +const getGroupedFilters = (filter: FilterItem) => + Array.isArray(filter) ? filter : filter?.meta?.params; + +const doForFilterByPath = ( + filters: FilterItem[], + path: string, + action: (filter: FilterItem) => T +) => { + const pathArray = getPathInArray(path); + let f = filters[pathArray[0]]; + for (let i = 1, depth = pathArray.length; i < depth; i++) { + f = getGroupedFilters(f)[+pathArray[i]]; + } + return action(f); +}; + +const getContainerMetaByPath = (filters: FilterItem[], pathInArray: number[]) => { + let targetArray: FilterItem[] = filters; + let parentFilter: FilterItem | undefined; + let parentConditionType = ConditionTypes.AND; + + if (pathInArray.length > 1) { + parentFilter = getFilterByPath(filters, getParentFilterPath(pathInArray)); + parentConditionType = getConditionalOperationType(parentFilter) ?? parentConditionType; + targetArray = getGroupedFilters(parentFilter); + } + + return { + parentFilter, + targetArray, + parentConditionType, + }; +}; + +const getParentFilterPath = (pathInArray: number[]) => + pathInArray.slice(0, -1).join(PATH_SEPARATOR); + +/** + * The method corrects the positions of the filters after removing some filter from the filters. + * @param {FilterItem[]} filters - an array of filters that may contain filters that are incorrectly nested for later display in the UI. + */ +export const normalizeFilters = (filters: FilterItem[]) => { + const doRecursive = (f: FilterItem, parent: FilterItem) => { + if (Array.isArray(f)) { + return normalizeArray(f, parent); + } else if (isOrFilter(f)) { + return normalizeOr(f); + } + return f; + }; + + const normalizeArray = (filtersArray: FilterItem[], parent: FilterItem): FilterItem[] => { + const partiallyNormalized = filtersArray + .map((item) => { + const normalized = doRecursive(item, filtersArray); + + if (Array.isArray(normalized)) { + if (normalized.length === 1) { + return normalized[0]; + } + if (normalized.length === 0) { + return undefined; + } + } + return normalized; + }, []) + .filter(Boolean) as FilterItem[]; + + return Array.isArray(parent) ? partiallyNormalized.flat() : partiallyNormalized; + }; + + const normalizeOr = (orFilter: Filter): FilterItem => { + const orFilters = getGroupedFilters(orFilter); + if (orFilters.length < 2) { + return orFilters[0]; + } + + return { + ...orFilter, + meta: { + ...orFilter.meta, + params: doRecursive(orFilters, orFilter), + }, + }; + }; + + return normalizeArray(filters, filters) as Filter[]; +}; + +/** + * Find filter by path. + * @param {FilterItem[]} filters - filters in which the search for the desired filter will occur. + * @param {string} path - path to filter. + */ +export const getFilterByPath = (filters: FilterItem[], path: string) => + doForFilterByPath(filters, path, (f) => f); + +/** + * Method to add a filter to a specified location in a filter group. + * @param {Filter[]} filters - array of filters where the new filter will be added. + * @param {FilterItem} filter - new filter. + * @param {string} path - path to filter. + * @param {ConditionTypes} conditionalType - OR/AND relationships between filters. + */ +export const addFilter = ( + filters: Filter[], + filter: FilterItem, + path: string, + conditionalType: ConditionTypes +) => { + const newFilters = cloneDeep(filters); + const pathInArray = getPathInArray(path); + const { targetArray, parentConditionType } = getContainerMetaByPath(newFilters, pathInArray); + const selector = pathInArray[pathInArray.length - 1]; + + if (parentConditionType !== conditionalType) { + if (conditionalType === ConditionTypes.OR) { + targetArray.splice(selector, 1, buildOrFilter([targetArray[selector], filter])); + } + if (conditionalType === ConditionTypes.AND) { + targetArray.splice(selector, 1, [targetArray[selector], filter]); + } + } else { + targetArray.splice(selector + 1, 0, filter); + } + + return newFilters; +}; + +/** + * Remove filter from specified location. + * @param {Filter[]} filters - array of filters. + * @param {string} path - path to filter. + */ +export const removeFilter = (filters: Filter[], path: string) => { + const newFilters = cloneDeep(filters); + const pathInArray = getPathInArray(path); + const { targetArray } = getContainerMetaByPath(newFilters, pathInArray); + const selector = pathInArray[pathInArray.length - 1]; + + targetArray.splice(selector, 1); + + return normalizeFilters(newFilters); +}; + +/** + * Moving the filter on drag and drop. + * @param {Filter[]} filters - array of filters. + * @param {string} from - filter path before moving. + * @param {string} to - filter path where the filter will be moved. + * @param {ConditionTypes} conditionalType - OR/AND relationships between filters. + */ +export const moveFilter = ( + filters: Filter[], + from: string, + to: string, + conditionalType: ConditionTypes +) => { + const addFilterThenRemoveFilter = ( + source: Filter[], + addedFilter: FilterItem, + pathFrom: string, + pathTo: string, + conditional: ConditionTypes + ) => { + const newFiltersWithFilter = addFilter(source, addedFilter, pathTo, conditional); + return removeFilter(newFiltersWithFilter, pathFrom); + }; + + const removeFilterThenAddFilter = ( + source: Filter[], + removableFilter: FilterItem, + pathFrom: string, + pathTo: string, + conditional: ConditionTypes + ) => { + const newFiltersWithoutFilter = removeFilter(source, pathFrom); + return addFilter(newFiltersWithoutFilter, removableFilter, pathTo, conditional); + }; + + const newFilters = cloneDeep(filters); + const movingFilter = getFilterByPath(newFilters, from); + + const pathInArrayTo = getPathInArray(to); + const pathInArrayFrom = getPathInArray(from); + + if (pathInArrayTo.length === pathInArrayFrom.length) { + const filterPositionTo = pathInArrayTo.at(-1); + const filterPositionFrom = pathInArrayFrom.at(-1); + + const { parentConditionType } = getContainerMetaByPath(newFilters, pathInArrayTo); + const filterMovementDirection = Number(filterPositionTo) - Number(filterPositionFrom); + + if (filterMovementDirection === -1 && parentConditionType === conditionalType) { + return filters; + } + + if (filterMovementDirection >= -1) { + return addFilterThenRemoveFilter(newFilters, movingFilter, from, to, conditionalType); + } else { + return removeFilterThenAddFilter(newFilters, movingFilter, from, to, conditionalType); + } + } + + if (pathInArrayTo.length > pathInArrayFrom.length) { + return addFilterThenRemoveFilter(newFilters, movingFilter, from, to, conditionalType); + } else { + return removeFilterThenAddFilter(newFilters, movingFilter, from, to, conditionalType); + } +}; + +/** + * Method to update values inside filter. + * @param {Filter[]} filters - filter array + * @param {string} path - path to filter + * @param {DataViewField} field - DataViewField property inside a filter + * @param {Operator} operator - defines a relation by property and value + * @param {Filter['meta']['params']} params - filter value + */ +export const updateFilter = ( + filters: Filter[], + path: string, + field?: DataViewField, + operator?: Operator, + params?: Filter['meta']['params'] +) => { + const newFilters = [...filters]; + const changedFilter = getFilterByPath(newFilters, path) as Filter; + let filter = Object.assign({}, changedFilter); + + if (field && operator && params) { + if (Array.isArray(params)) { + filter = updateWithIsOneOfOperator(filter, operator, params); + } else { + filter = updateWithIsOperator(filter, operator, params); + } + } else if (field && operator) { + if (operator.type === 'exists') { + filter = updateWithExistsOperator(filter, operator); + } else { + filter = updateOperator(filter, operator); + } + } else { + filter = updateField(filter, field); + } + + const pathInArray = getPathInArray(path); + const { targetArray } = getContainerMetaByPath(newFilters, pathInArray); + const selector = pathInArray[pathInArray.length - 1]; + targetArray.splice(selector, 1, filter); + + return newFilters; +}; + +function updateField(filter: Filter, field?: DataViewField) { + return { + ...filter, + meta: { + ...filter.meta, + key: field?.name, + params: { query: undefined }, + value: undefined, + type: undefined, + }, + query: undefined, + }; +} + +function updateOperator(filter: Filter, operator?: Operator) { + return { + ...filter, + meta: { + ...filter.meta, + negate: operator?.negate, + type: operator?.type, + params: { ...filter.meta.params, query: undefined }, + value: undefined, + }, + query: { match_phrase: { field: filter.meta.key } }, + }; +} + +function updateWithExistsOperator(filter: Filter, operator?: Operator) { + return { + ...filter, + meta: { + ...filter.meta, + negate: operator?.negate, + type: operator?.type, + params: undefined, + value: 'exists', + }, + query: { exists: { field: filter.meta.key } }, + }; +} + +function updateWithIsOperator( + filter: Filter, + operator?: Operator, + params?: Filter['meta']['params'] +) { + return { + ...filter, + meta: { + ...filter.meta, + negate: operator?.negate, + type: operator?.type, + params: { ...filter.meta.params, query: params }, + }, + query: { match_phrase: { ...filter!.query?.match_phrase, [filter.meta.key!]: params } }, + }; +} + +function updateWithIsOneOfOperator( + filter: Filter, + operator?: Operator, + params?: Array +) { + return { + ...filter, + meta: { + ...filter.meta, + negate: operator?.negate, + type: operator?.type, + params, + }, + query: { + bool: { + minimum_should_match: 1, + ...filter!.query?.should, + should: params?.map((param) => { + return { match_phrase: { [filter.meta.key!]: param } }; + }), + }, + }, + }; +} diff --git a/src/plugins/unified_search/public/filters_builder/index.ts b/src/plugins/unified_search/public/filters_builder/index.ts new file mode 100644 index 00000000000000..0f430ca87aaac9 --- /dev/null +++ b/src/plugins/unified_search/public/filters_builder/index.ts @@ -0,0 +1,22 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import React from 'react'; +import { withSuspense } from '@kbn/shared-ux-utility'; + +/** + * The Lazily-loaded `FiltersBuilder` component. Consumers should use `React.Suspense` or + * the withSuspense` HOC to load this component. + */ +export const FiltersBuilderLazy = React.lazy(() => import('./filters_builder')); + +/** + * A `FiltersBuilder` component that is wrapped by the `withSuspense` HOC. This component can + * be used directly by consumers and will load the `FiltersBuilderLazy` component lazily with + * a predefined fallback and error boundary. + */ +export const FiltersBuilder = withSuspense(FiltersBuilderLazy); diff --git a/src/plugins/unified_search/public/index.ts b/src/plugins/unified_search/public/index.ts index 131b4450173537..731396014d8354 100755 --- a/src/plugins/unified_search/public/index.ts +++ b/src/plugins/unified_search/public/index.ts @@ -12,7 +12,11 @@ export type { IndexPatternSelectProps } from './index_pattern_select'; export type { QueryStringInputProps } from './query_string_input'; export { QueryStringInput } from './query_string_input'; export type { StatefulSearchBarProps, SearchBarProps } from './search_bar'; -export type { UnifiedSearchPublicPluginStart, UnifiedSearchPluginSetup } from './types'; +export type { + UnifiedSearchPublicPluginStart, + UnifiedSearchPluginSetup, + IUnifiedSearchPluginServices, +} from './types'; export { SearchBar } from './search_bar'; export type { FilterItemsProps } from './filter_bar'; export { FilterLabel, FilterItem, FilterItems } from './filter_bar'; diff --git a/src/plugins/unified_search/public/plugin.ts b/src/plugins/unified_search/public/plugin.ts index 05e22b035614d2..e853e6b77e8e12 100755 --- a/src/plugins/unified_search/public/plugin.ts +++ b/src/plugins/unified_search/public/plugin.ts @@ -11,7 +11,7 @@ import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import { APPLY_FILTER_TRIGGER } from '@kbn/data-plugin/public'; import { UPDATE_FILTER_REFERENCES_TRIGGER, updateFilterReferencesTrigger } from './triggers'; import { ConfigSchema } from '../config'; -import { setIndexPatterns, setTheme, setOverlays, setAutocomplete } from './services'; +import { setIndexPatterns, setTheme, setOverlays } from './services'; import { AutocompleteService } from './autocomplete/autocomplete_service'; import { createSearchBar } from './search_bar'; import { createIndexPatternSelect } from './index_pattern_select'; @@ -70,7 +70,6 @@ export class UnifiedSearchPublicPlugin setOverlays(core.overlays); setIndexPatterns(dataViews); const autocompleteStart = this.autocomplete.start(); - setAutocomplete(autocompleteStart); const SearchBar = createSearchBar({ core, @@ -78,6 +77,9 @@ export class UnifiedSearchPublicPlugin storage: this.storage, usageCollection: this.usageCollection, isScreenshotMode: Boolean(screenshotMode?.isScreenshotMode()), + unifiedSearch: { + autocomplete: autocompleteStart, + }, }); uiActions.addTriggerAction( diff --git a/src/plugins/unified_search/public/query_string_input/filter_editor_wrapper.tsx b/src/plugins/unified_search/public/query_string_input/filter_editor_wrapper.tsx index dd106607353f2f..a0e36688a2f8b8 100644 --- a/src/plugins/unified_search/public/query_string_input/filter_editor_wrapper.tsx +++ b/src/plugins/unified_search/public/query_string_input/filter_editor_wrapper.tsx @@ -11,8 +11,8 @@ import { Filter, buildEmptyFilter } from '@kbn/es-query'; import { METRIC_TYPE } from '@kbn/analytics'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; +import type { IUnifiedSearchPluginServices } from '../types'; import { FILTER_EDITOR_WIDTH } from '../filter_bar/filter_item/filter_item'; import { FilterEditor } from '../filter_bar/filter_editor'; import { fetchIndexPatterns } from './fetch_index_patterns'; @@ -32,7 +32,7 @@ export const FilterEditorWrapper = React.memo(function FilterEditorWrapper({ closePopover, onFiltersUpdated, }: FilterEditorWrapperProps) { - const kibana = useKibana(); + const kibana = useKibana(); const { uiSettings, data, usageCollection, appName } = kibana.services; const reportUiCounter = usageCollection?.reportUiCounter.bind(usageCollection, appName); const [dataViews, setDataviews] = useState([]); diff --git a/src/plugins/unified_search/public/query_string_input/query_bar_menu_panels.tsx b/src/plugins/unified_search/public/query_string_input/query_bar_menu_panels.tsx index 2b5dbf4999af14..4a921c3a1d1777 100644 --- a/src/plugins/unified_search/public/query_string_input/query_bar_menu_panels.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_bar_menu_panels.tsx @@ -29,7 +29,8 @@ import { import { METRIC_TYPE } from '@kbn/analytics'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { KIBANA_USER_QUERY_LANGUAGE_KEY, UI_SETTINGS } from '@kbn/data-plugin/common'; -import type { IDataPluginServices, SavedQueryService, SavedQuery } from '@kbn/data-plugin/public'; +import type { SavedQueryService, SavedQuery } from '@kbn/data-plugin/public'; +import type { IUnifiedSearchPluginServices } from '../types'; import { fromUser } from './from_user'; import { QueryLanguageSwitcher } from './language_switcher'; import { FilterPanelOption } from '../types'; @@ -88,7 +89,7 @@ export function QueryBarMenuPanels({ onQueryChange, setRenderedComponent, }: QueryBarMenuPanelsProps) { - const kibana = useKibana(); + const kibana = useKibana(); const { appName, usageCollection, uiSettings, http, storage } = kibana.services; const reportUiCounter = usageCollection?.reportUiCounter.bind(usageCollection, appName); const cancelPendingListingRequest = useRef<() => void>(() => {}); diff --git a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.test.tsx b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.test.tsx index 1f879ebcae9a86..052e0ab7b32c82 100644 --- a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.test.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.test.tsx @@ -20,7 +20,6 @@ import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { I18nProvider } from '@kbn/i18n-react'; import { stubIndexPattern } from '@kbn/data-plugin/public/stubs'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { setAutocomplete } from '../services'; import { unifiedSearchPluginMock } from '../mocks'; const startMock = coreMock.createStart(); @@ -96,6 +95,7 @@ function wrapQueryBarTopRowInContext(testProps: any) { const services = { ...startMock, + unifiedSearch: unifiedSearchPluginMock.createStartContract(), data: dataPluginMock.createStartContract(), appName: 'discover', storage: createMockStorage(), @@ -120,11 +120,6 @@ describe('QueryBarTopRowTopRow', () => { jest.clearAllMocks(); }); - beforeEach(() => { - const autocompleteStart = unifiedSearchPluginMock.createStartContract(); - setAutocomplete(autocompleteStart.autocomplete); - }); - it('Should render query and time picker', () => { const { getByText, getByTestId } = render( wrapQueryBarTopRowInContext({ diff --git a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx index ef6f09f679de21..c0848f630daa80 100644 --- a/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_bar_top_row.tsx @@ -26,12 +26,13 @@ import { useIsWithinBreakpoints, EuiSuperUpdateButton, } from '@elastic/eui'; -import { IDataPluginServices, TimeHistoryContract, getQueryLog } from '@kbn/data-plugin/public'; +import { TimeHistoryContract, getQueryLog } from '@kbn/data-plugin/public'; import { i18n } from '@kbn/i18n'; import { DataView } from '@kbn/data-views-plugin/public'; import type { PersistedLog } from '@kbn/data-plugin/public'; import { useKibana, withKibana } from '@kbn/kibana-react-plugin/public'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; +import type { IUnifiedSearchPluginServices } from '../types'; import QueryStringInputUI from './query_string_input'; import { NoDataPopover } from './no_data_popover'; import { shallowEqual } from '../utils/shallow_equal'; @@ -164,7 +165,7 @@ export const QueryBarTopRow = React.memo( const [isDateRangeInvalid, setIsDateRangeInvalid] = useState(false); const [isQueryInputFocused, setIsQueryInputFocused] = useState(false); - const kibana = useKibana(); + const kibana = useKibana(); const { uiSettings, storage, appName } = kibana.services; const isQueryLangSelected = props.query && !isOfQueryType(props.query); diff --git a/src/plugins/unified_search/public/query_string_input/query_string_input.test.tsx b/src/plugins/unified_search/public/query_string_input/query_string_input.test.tsx index 7437bf5fd4ece9..41060aaecb3df1 100644 --- a/src/plugins/unified_search/public/query_string_input/query_string_input.test.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_string_input.test.tsx @@ -27,12 +27,9 @@ import { coreMock } from '@kbn/core/public/mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { stubIndexPattern } from '@kbn/data-plugin/public/stubs'; import { KibanaContextProvider, withKibana } from '@kbn/kibana-react-plugin/public'; - -import { setAutocomplete } from '../services'; import { unifiedSearchPluginMock } from '../mocks'; jest.useFakeTimers(); - const startMock = coreMock.createStart(); const noop = () => { @@ -71,6 +68,7 @@ const QueryStringInput = withKibana(QueryStringInputUI); function wrapQueryStringInputInContext(testProps: any, storage?: any) { const services = { ...startMock, + unifiedSearch: unifiedSearchPluginMock.createStartContract(), data: dataPluginMock.createStartContract(), appName: testProps.appName || 'test', storage: storage || createMockStorage(), @@ -95,11 +93,6 @@ describe('QueryStringInput', () => { jest.clearAllMocks(); }); - beforeEach(() => { - const autocompleteStart = unifiedSearchPluginMock.createStartContract(); - setAutocomplete(autocompleteStart.autocomplete); - }); - it('Should render the given query', async () => { const { getByText } = render( wrapQueryStringInputInContext({ diff --git a/src/plugins/unified_search/public/query_string_input/query_string_input.tsx b/src/plugins/unified_search/public/query_string_input/query_string_input.tsx index c37e050b0823ad..84a12d8c632004 100644 --- a/src/plugins/unified_search/public/query_string_input/query_string_input.tsx +++ b/src/plugins/unified_search/public/query_string_input/query_string_input.tsx @@ -30,7 +30,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { compact, debounce, isEmpty, isEqual, isFunction } from 'lodash'; import { Toast } from '@kbn/core/public'; import type { Query } from '@kbn/es-query'; -import { IDataPluginServices, getQueryLog } from '@kbn/data-plugin/public'; +import { getQueryLog } from '@kbn/data-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; import type { PersistedLog } from '@kbn/data-plugin/public'; import { getFieldSubtypeNested, KIBANA_USER_QUERY_LANGUAGE_KEY } from '@kbn/data-plugin/common'; @@ -41,11 +41,12 @@ import { fromUser } from './from_user'; import { fetchIndexPatterns } from './fetch_index_patterns'; import { QueryLanguageSwitcher } from './language_switcher'; import type { SuggestionsListSize } from '../typeahead/suggestions_component'; +import type { IUnifiedSearchPluginServices } from '../types'; import { SuggestionsComponent } from '../typeahead'; import { onRaf } from '../utils'; import { FilterButtonGroup } from '../filter_bar/filter_button_group/filter_button_group'; import { QuerySuggestion, QuerySuggestionTypes } from '../autocomplete'; -import { getTheme, getAutocomplete } from '../services'; +import { getTheme } from '../services'; import './query_string_input.scss'; export interface QueryStringInputProps { @@ -93,7 +94,7 @@ export interface QueryStringInputProps { } interface Props extends QueryStringInputProps { - kibana: KibanaReactContextValue; + kibana: KibanaReactContextValue; } interface State { @@ -202,7 +203,9 @@ export default class QueryStringInputUI extends PureComponent { const queryString = this.getQueryString(); const recentSearchSuggestions = this.getRecentSearchSuggestions(queryString); - const hasQuerySuggestions = getAutocomplete().hasQuerySuggestions(language); + const hasQuerySuggestions = await this.services.unifiedSearch.autocomplete.hasQuerySuggestions( + language + ); if ( !hasQuerySuggestions || @@ -223,7 +226,7 @@ export default class QueryStringInputUI extends PureComponent { if (this.abortController) this.abortController.abort(); this.abortController = new AbortController(); const suggestions = - (await getAutocomplete().getQuerySuggestions({ + (await this.services.unifiedSearch.autocomplete.getQuerySuggestions({ language, indexPatterns, query: queryString, diff --git a/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx b/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx index 9b6bb6707ab49c..54343ec245efe8 100644 --- a/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx +++ b/src/plugins/unified_search/public/query_string_input/text_based_languages_editor/index.tsx @@ -9,7 +9,6 @@ import React, { useRef, memo, useEffect, useState, useCallback } from 'react'; import classNames from 'classnames'; import { EsqlLang, monaco } from '@kbn/monaco'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import type { AggregateQuery } from '@kbn/es-query'; import { getAggregateQueryMode } from '@kbn/es-query'; import { useKibana } from '@kbn/kibana-react-plugin/public'; @@ -47,6 +46,7 @@ import { EditorFooter } from './editor_footer'; import { ResizableButton } from './resizable_button'; import './overwrite.scss'; +import { IUnifiedSearchPluginServices } from '../../types'; export interface TextBasedLanguagesEditorProps { query: AggregateQuery; @@ -106,7 +106,7 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ Array<{ startLineNumber: number; message: string }> >([]); const [documentationSections, setDocumentationSections] = useState(); - const kibana = useKibana(); + const kibana = useKibana(); const { uiSettings } = kibana.services; const styles = textBasedLanguagedEditorStyles( diff --git a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx index 6200af754507a6..15f5295e5ee36e 100644 --- a/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx +++ b/src/plugins/unified_search/public/saved_query_management/saved_query_management_list.tsx @@ -27,9 +27,10 @@ import React, { useCallback, useEffect, useState, useRef } from 'react'; import { css } from '@emotion/react'; import { sortBy } from 'lodash'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { IDataPluginServices, SavedQuery, SavedQueryService } from '@kbn/data-plugin/public'; +import { SavedQuery, SavedQueryService } from '@kbn/data-plugin/public'; import type { SavedQueryAttributes } from '@kbn/data-plugin/common'; import './saved_query_management_list.scss'; +import type { IUnifiedSearchPluginServices } from '../types'; export interface SavedQueryManagementListProps { showSaveQuery?: boolean; @@ -120,7 +121,7 @@ export function SavedQueryManagementList({ onClose, hasFiltersOrQuery, }: SavedQueryManagementListProps) { - const kibana = useKibana(); + const kibana = useKibana(); const [savedQueries, setSavedQueries] = useState([] as SavedQuery[]); const [selectedSavedQuery, setSelectedSavedQuery] = useState(null as SavedQuery | null); const [toBeDeletedSavedQuery, setToBeDeletedSavedQuery] = useState(null as SavedQuery | null); diff --git a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx index 39980f03e3cbe7..a4df4d0f1a76ec 100644 --- a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx @@ -21,13 +21,15 @@ import { useFilterManager } from './lib/use_filter_manager'; import { useTimefilter } from './lib/use_timefilter'; import { useSavedQuery } from './lib/use_saved_query'; import { useQueryStringManager } from './lib/use_query_string_manager'; +import { UnifiedSearchPublicPluginStart } from '../types'; interface StatefulSearchBarDeps { core: CoreStart; - data: Omit; + data: DataPublicPluginStart; storage: IStorageWrapper; usageCollection?: UsageCollectionSetup; isScreenshotMode?: boolean; + unifiedSearch: Omit; } export type StatefulSearchBarProps = @@ -127,6 +129,7 @@ export function createSearchBar({ data, usageCollection, isScreenshotMode = false, + unifiedSearch, }: StatefulSearchBarDeps) { // App name should come from the core application service. // Until it's available, we'll ask the user to provide it for the pre-wired component. @@ -179,6 +182,7 @@ export function createSearchBar({ data, storage, usageCollection, + unifiedSearch, ...core, }} > diff --git a/src/plugins/unified_search/public/search_bar/search_bar.tsx b/src/plugins/unified_search/public/search_bar/search_bar.tsx index ecfbb388081ba6..8a6396d9939733 100644 --- a/src/plugins/unified_search/public/search_bar/search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/search_bar.tsx @@ -19,9 +19,9 @@ import { Query, Filter, TimeRange, AggregateQuery, isOfQueryType } from '@kbn/es import { withKibana, KibanaReactContextValue } from '@kbn/kibana-react-plugin/public'; import type { TimeHistoryContract, SavedQuery } from '@kbn/data-plugin/public'; import type { SavedQueryAttributes } from '@kbn/data-plugin/common'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; +import type { IUnifiedSearchPluginServices } from '../types'; import { SavedQueryMeta, SaveQueryForm } from '../saved_query_form'; import { SavedQueryManagementList } from '../saved_query_management'; import { QueryBarMenu, QueryBarMenuProps } from '../query_string_input/query_bar_menu'; @@ -32,7 +32,7 @@ import type { SuggestionsListSize } from '../typeahead/suggestions_component'; import { searchBarStyles } from './search_bar.styles'; export interface SearchBarInjectedDeps { - kibana: KibanaReactContextValue; + kibana: KibanaReactContextValue; intl: InjectedIntl; timeHistory?: TimeHistoryContract; // Filter bar diff --git a/src/plugins/unified_search/public/services.ts b/src/plugins/unified_search/public/services.ts index f67801dd377300..4f8937baf8fdf0 100644 --- a/src/plugins/unified_search/public/services.ts +++ b/src/plugins/unified_search/public/services.ts @@ -9,7 +9,6 @@ import { ThemeServiceStart, OverlayStart } from '@kbn/core/public'; import { createGetterSetter } from '@kbn/kibana-utils-plugin/public'; import { DataViewsContract } from '@kbn/data-views-plugin/public'; -import { AutocompleteStart } from '.'; export const [getIndexPatterns, setIndexPatterns] = createGetterSetter('IndexPatterns'); @@ -17,6 +16,3 @@ export const [getIndexPatterns, setIndexPatterns] = export const [getTheme, setTheme] = createGetterSetter('Theme'); export const [getOverlays, setOverlays] = createGetterSetter('Overlays'); - -export const [getAutocomplete, setAutocomplete] = - createGetterSetter('Autocomplete'); diff --git a/src/plugins/unified_search/public/types.ts b/src/plugins/unified_search/public/types.ts index 3189e7cf32d08c..246fc87114db48 100755 --- a/src/plugins/unified_search/public/types.ts +++ b/src/plugins/unified_search/public/types.ts @@ -11,8 +11,10 @@ import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { ScreenshotModePluginStart } from '@kbn/screenshot-mode-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; +import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import { Query, AggregateQuery } from '@kbn/es-query'; +import { CoreStart } from '@kbn/core/public'; +import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { AutocompleteSetup, AutocompleteStart } from './autocomplete'; import type { IndexPatternSelectProps, StatefulSearchBarProps } from '.'; @@ -56,7 +58,7 @@ export interface UnifiedSearchPublicPluginStart { autocomplete: AutocompleteStart; /** * prewired UI components - * {@link DataPublicPluginStartUi} + * {@link UnifiedSearchPublicPluginStartUi} */ ui: UnifiedSearchPublicPluginStartUi; } @@ -70,3 +72,18 @@ export type FilterPanelOption = | 'negateFilter' | 'disableFilter' | 'deleteFilter'; + +export interface IUnifiedSearchPluginServices extends Partial { + unifiedSearch: { + autocomplete: AutocompleteStart; + }; + appName: string; + uiSettings: CoreStart['uiSettings']; + savedObjects: CoreStart['savedObjects']; + notifications: CoreStart['notifications']; + application: CoreStart['application']; + http: CoreStart['http']; + storage: IStorageWrapper; + data: DataPublicPluginStart; + usageCollection?: UsageCollectionStart; +} diff --git a/src/plugins/unified_search/public/utils/index.ts b/src/plugins/unified_search/public/utils/index.ts index 5dffd3798399db..395304c48a9145 100644 --- a/src/plugins/unified_search/public/utils/index.ts +++ b/src/plugins/unified_search/public/utils/index.ts @@ -8,3 +8,11 @@ export { onRaf } from './on_raf'; export { shallowEqual } from './shallow_equal'; + +export type { FilterItem } from './or_filter'; +export { + ConditionTypes, + isOrFilter, + getConditionalOperationType, + buildOrFilter, +} from './or_filter'; diff --git a/src/plugins/unified_search/public/utils/or_filter.ts b/src/plugins/unified_search/public/utils/or_filter.ts new file mode 100644 index 00000000000000..419e4f04d74ae0 --- /dev/null +++ b/src/plugins/unified_search/public/utils/or_filter.ts @@ -0,0 +1,47 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +// Methods from this file will be removed after they are moved to the package +import { buildEmptyFilter, Filter } from '@kbn/es-query'; + +export enum ConditionTypes { + OR = 'OR', + AND = 'AND', +} + +/** @internal **/ +export type FilterItem = Filter | FilterItem[]; + +/** to: @kbn/es-query **/ +export const isOrFilter = (filter: Filter) => Boolean(filter?.meta?.type === 'OR'); + +/** + * Defines a conditional operation type (AND/OR) from the filter otherwise returns undefined. + * @param {FilterItem} filter + */ +export const getConditionalOperationType = (filter: FilterItem) => { + if (Array.isArray(filter)) { + return ConditionTypes.AND; + } else if (isOrFilter(filter)) { + return ConditionTypes.OR; + } +}; + +/** to: @kbn/es-query **/ +export const buildOrFilter = (filters: FilterItem) => { + const filter = buildEmptyFilter(false); + + return { + ...filter, + meta: { + ...filter.meta, + type: 'OR', + params: filters, + }, + }; +}; diff --git a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index 77a56eadee526f..3f95b6adf6b451 100644 --- a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -20,8 +20,8 @@ import { i18n } from '@kbn/i18n'; import classNames from 'classnames'; import { FormattedMessage } from '@kbn/i18n-react'; import { connect } from 'react-redux'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { IUnifiedSearchPluginServices } from '@kbn/unified-search-plugin/public/types'; import { GraphState, hasDatasourceSelector, @@ -75,7 +75,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) { const { onFillWorkspace, onOpenFieldPicker, onIndexPatternSelected, hasDatasource, hasFields } = props; - const kibana = useKibana(); + const kibana = useKibana(); const { services, overlays } = kibana; const { savedObjects, uiSettings, application, data } = services; const [hasDataViews, setHasDataViews] = useState(true); diff --git a/x-pack/plugins/graph/public/components/search_bar.test.tsx b/x-pack/plugins/graph/public/components/search_bar.test.tsx index 3fbf7222d15297..de9598b52087ea 100644 --- a/x-pack/plugins/graph/public/components/search_bar.test.tsx +++ b/x-pack/plugins/graph/public/components/search_bar.test.tsx @@ -19,8 +19,6 @@ import { import { act } from 'react-dom/test-utils'; import { QueryStringInput } from '@kbn/unified-search-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; -import { setAutocomplete } from '@kbn/unified-search-plugin/public/services'; -import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { I18nProvider, InjectedIntl } from '@kbn/i18n-react'; @@ -106,11 +104,6 @@ describe('search_bar', () => { }, }; - beforeEach(() => { - const autocompleteStart = unifiedSearchPluginMock.createStartContract(); - setAutocomplete(autocompleteStart.autocomplete); - }); - beforeEach(() => { store = createMockGraphStore({ sagas: [submitSearchSaga], diff --git a/x-pack/plugins/graph/public/components/search_bar.tsx b/x-pack/plugins/graph/public/components/search_bar.tsx index 30f3fad82dafc9..9aa05f64754cdd 100644 --- a/x-pack/plugins/graph/public/components/search_bar.tsx +++ b/x-pack/plugins/graph/public/components/search_bar.tsx @@ -12,9 +12,9 @@ import { i18n } from '@kbn/i18n'; import { connect } from 'react-redux'; import { toElasticsearchQuery, fromKueryExpression, Query } from '@kbn/es-query'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { IDataPluginServices } from '@kbn/data-plugin/public'; import { QueryStringInput } from '@kbn/unified-search-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; +import { IUnifiedSearchPluginServices } from '@kbn/unified-search-plugin/public/types'; import { IndexPatternSavedObject, IndexPatternProvider, WorkspaceField } from '../types'; import { openSourceModal } from '../services/source_modal'; import { @@ -95,7 +95,7 @@ export function SearchBarComponent(props: SearchBarStateProps & SearchBarProps) fetchPattern(); }, [currentDatasource, indexPatternProvider, onIndexPatternChange]); - const kibana = useKibana(); + const kibana = useKibana(); const { services, overlays } = kibana; const { savedObjects, uiSettings } = services; if (!overlays) return null; diff --git a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx index fadf1767b1db6f..b9e95a2ee837e3 100644 --- a/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/query_bar/index.test.tsx @@ -15,8 +15,6 @@ import { FilterManager } from '@kbn/data-plugin/public'; import { SearchBar } from '@kbn/unified-search-plugin/public'; import type { QueryBarComponentProps } from '.'; import { QueryBar } from '.'; -import { setAutocomplete } from '@kbn/unified-search-plugin/public/services'; -import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; const mockUiSettingsForFilterManager = coreMock.createStart().uiSettings; @@ -275,11 +273,6 @@ describe('QueryBar ', () => { }); describe('#onSavedQueryUpdated', () => { - beforeEach(() => { - const autocompleteStart = unifiedSearchPluginMock.createStartContract(); - setAutocomplete(autocompleteStart.autocomplete); - }); - test('is only reference that changed when dataProviders props get updated', async () => { await act(async () => { const wrapper = await getWrapper( diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx index 385449d8754b61..c1c18c4c3cd3c9 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx @@ -7,7 +7,7 @@ import React, { memo, useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSuperDatePicker } from '@elastic/eui'; -import type { IDataPluginServices } from '@kbn/data-plugin/public'; +import type { IUnifiedSearchPluginServices } from '@kbn/unified-search-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import type { EuiSuperDatePickerRecentRange } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; @@ -16,7 +16,6 @@ import type { OnRefreshChangeProps, } from '@elastic/eui/src/components/date_picker/types'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; - import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; import { useActionHistoryUrlParams } from './use_action_history_url_params'; @@ -52,7 +51,7 @@ export const ActionLogDateRangePicker = memo( }) => { const { startDate: startDateFromUrl, endDate: endDateFromUrl } = useActionHistoryUrlParams(); const getTestId = useTestIdGenerator('response-actions-list'); - const kibana = useKibana(); + const kibana = useKibana(); const { uiSettings } = kibana.services; const [commonlyUsedRanges] = useState(() => { return ( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx index a1fcefceadfb5b..3cf7acdef93fb3 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.test.tsx @@ -18,8 +18,6 @@ import { FilterStateStore } from '@kbn/es-query'; import { FilterManager } from '@kbn/data-plugin/public'; import { mockDataProviders } from '../data_providers/mock/mock_data_providers'; import { buildGlobalQuery } from '../helpers'; -import { setAutocomplete } from '@kbn/unified-search-plugin/public/services'; -import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; import type { QueryBarTimelineComponentProps } from '.'; import { QueryBarTimeline, getDataProviderFilter, TIMELINE_FILTER_DROP_AREA } from '.'; @@ -182,11 +180,6 @@ describe('Timeline QueryBar ', () => { }); describe('#onSavedQuery', () => { - beforeEach(() => { - const autocompleteStart = unifiedSearchPluginMock.createStartContract(); - setAutocomplete(autocompleteStart.autocomplete); - }); - test('is only reference that changed when dataProviders props get updated', async () => { const Proxy = (props: QueryBarTimelineComponentProps) => ( diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx index f3808984137df4..b3aa4714fa6647 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/pages/overview.test.tsx @@ -8,15 +8,8 @@ import React from 'react'; import { OverviewPageComponent } from './overview'; import { render } from '../lib/helper/rtl_helpers'; -import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; -import { setAutocomplete } from '@kbn/unified-search-plugin/public/services'; describe('MonitorPage', () => { - beforeEach(() => { - const autocompleteStart = unifiedSearchPluginMock.createStartContract(); - setAutocomplete(autocompleteStart.autocomplete); - }); - it('renders expected elements for valid props', async () => { const { findByText, findByPlaceholderText } = render(); diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/query_bar/query_bar.test.tsx b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/query_bar/query_bar.test.tsx index bb05a23feb1746..2ab2795e138bdb 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/query_bar/query_bar.test.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/components/query_bar/query_bar.test.tsx @@ -13,9 +13,8 @@ import userEvent from '@testing-library/user-event'; import { FilterManager } from '@kbn/data-plugin/public'; import { coreMock } from '@kbn/core/public/mocks'; -import { TestProvidersComponent, unifiedSearch } from '../../../../common/mocks/test_providers'; +import { TestProvidersComponent } from '../../../../common/mocks/test_providers'; import { getByTestSubj } from '../../../../../common/test/utils'; -import { setAutocomplete } from '@kbn/unified-search-plugin/public/services'; const mockUiSettingsForFilterManager = coreMock.createStart().uiSettings; @@ -27,10 +26,6 @@ describe('QueryBar ', () => { const onSavedQuery = jest.fn(); const onChangedQuery = jest.fn(); - beforeEach(() => { - setAutocomplete(unifiedSearch.autocomplete); - }); - beforeEach(async () => { await act(async () => { render( From 6e753338879c9e910867395c41c148d0b65856ab Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 13 Sep 2022 10:49:19 -0400 Subject: [PATCH 119/144] Revert "[cft] Temporarily disable cloud deployments (#140538)" (#140622) This reverts commit e741176614c09354cd96f3feced7249a55326b02. --- .buildkite/scripts/steps/cloud/build_and_deploy.sh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.buildkite/scripts/steps/cloud/build_and_deploy.sh b/.buildkite/scripts/steps/cloud/build_and_deploy.sh index f9b2a3fc928d2e..017e25bb288508 100755 --- a/.buildkite/scripts/steps/cloud/build_and_deploy.sh +++ b/.buildkite/scripts/steps/cloud/build_and_deploy.sh @@ -2,14 +2,6 @@ set -euo pipefail -echo "Cloud deployments have been temporarily disabled. We're investigating, status updates will be posted in #kibana-operations." -cat << EOF | buildkite-agent annotate --style "error" --context cloud - ### Cloud Deployment - - Cloud deployments have been temporarily disabled. We're investigating, status updates will be posted in #kibana-operations. -EOF -exit 0 - source .buildkite/scripts/common/util.sh .buildkite/scripts/bootstrap.sh From 2f1f9e0b5d4f02cbd0ade21f43b90095c3282f55 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 13 Sep 2022 07:50:47 -0700 Subject: [PATCH 120/144] [Filters] Update filter meta to not include formatter functions (#136906) * Update filter meta to not include formatter functions * Fix failing tests * Update tests * Fix functional test & phrase mapper * Update scripted field handling * Look up field from getFilterField * Make meta optional * Fix failing tests * Fix dataTestSubj values * Fix scripted range filter display Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../filters/build_filters/get_filter_field.ts | 8 +-- .../build_filters/phrase_filter.test.ts | 10 +++ .../filters/build_filters/phrase_filter.ts | 7 +- .../src/filters/build_filters/range_filter.ts | 6 +- .../common/es_query/stubs/phrase_filter.ts | 6 +- .../common/es_query/stubs/range_filter.ts | 2 +- src/plugins/data/common/index.ts | 1 - src/plugins/data/common/types.ts | 6 -- .../lib/get_display_value.test.ts | 62 +++++++++++------ .../filter_manager/lib/get_display_value.ts | 41 ++++++++---- .../lib/map_and_flatten_filters.test.ts | 11 +--- .../filter_manager/lib/map_filter.test.ts | 17 ++--- .../lib/mappers/map_phrase.test.ts | 38 ++++++++--- .../filter_manager/lib/mappers/map_phrase.ts | 19 +++--- .../lib/mappers/map_phrases.test.ts | 61 +++++++++++++++++ .../filter_manager/lib/mappers/map_phrases.ts | 23 +++---- .../lib/mappers/map_range.test.ts | 66 +++++++++++++++++-- .../filter_manager/lib/mappers/map_range.ts | 46 +++++++------ .../context/services/context_state.test.ts | 4 +- .../filter_bar/filter_item/filter_item.tsx | 5 +- 20 files changed, 302 insertions(+), 137 deletions(-) create mode 100644 src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.test.ts diff --git a/packages/kbn-es-query/src/filters/build_filters/get_filter_field.ts b/packages/kbn-es-query/src/filters/build_filters/get_filter_field.ts index 9ae820cfea4e7a..d8ef7e1106c0ba 100644 --- a/packages/kbn-es-query/src/filters/build_filters/get_filter_field.ts +++ b/packages/kbn-es-query/src/filters/build_filters/get_filter_field.ts @@ -8,8 +8,8 @@ import { getExistsFilterField, isExistsFilter } from './exists_filter'; import { getPhrasesFilterField, isPhrasesFilter } from './phrases_filter'; -import { getPhraseFilterField, isPhraseFilter } from './phrase_filter'; -import { getRangeFilterField, isRangeFilter } from './range_filter'; +import { getPhraseFilterField, isPhraseFilter, isScriptedPhraseFilter } from './phrase_filter'; +import { getRangeFilterField, isRangeFilter, isScriptedRangeFilter } from './range_filter'; import type { Filter } from './types'; /** @internal */ @@ -17,13 +17,13 @@ export const getFilterField = (filter: Filter) => { if (isExistsFilter(filter)) { return getExistsFilterField(filter); } - if (isPhraseFilter(filter)) { + if (isPhraseFilter(filter) || isScriptedPhraseFilter(filter)) { return getPhraseFilterField(filter); } if (isPhrasesFilter(filter)) { return getPhrasesFilterField(filter); } - if (isRangeFilter(filter)) { + if (isRangeFilter(filter) || isScriptedRangeFilter(filter)) { return getRangeFilterField(filter); } diff --git a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts index 7c7f7dd28f6cad..1088ba196840c2 100644 --- a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts +++ b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts @@ -186,4 +186,14 @@ describe('isScriptedPhraseFilter', () => { expect(isScriptedPhraseFilter(filter)).toBe(true); expect(isPhraseFilter(unknownFilter)).toBe(false); }); + + it('should return false if the filter is a range filter', () => { + const filter: Filter = set({ meta: {} }, 'query.script.script.params', { + gt: 0, + lt: 100, + value: 100, + }) as Filter; + + expect(isScriptedPhraseFilter(filter)).toBe(false); + }); }); diff --git a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts index 752dc8b338661e..3bbf94cd0722a2 100644 --- a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts @@ -10,6 +10,7 @@ import { get, has, isPlainObject } from 'lodash'; import type { Filter, FilterMeta } from './types'; import type { DataViewFieldBase, DataViewBase } from '../../es_query'; import { getConvertedValueForField } from './get_converted_value_for_field'; +import { hasRangeKeys } from './range_filter'; export type PhraseFilterValue = string | number | boolean; @@ -60,10 +61,12 @@ export const isPhraseFilter = (filter: Filter): filter is PhraseFilter => { * @public */ export const isScriptedPhraseFilter = (filter: Filter): filter is ScriptedPhraseFilter => - has(filter, 'query.script.script.params.value'); + has(filter, 'query.script.script.params.value') && + !hasRangeKeys(filter.query?.script?.script?.params); /** @internal */ -export const getPhraseFilterField = (filter: PhraseFilter) => { +export const getPhraseFilterField = (filter: PhraseFilter | ScriptedPhraseFilter) => { + if (filter.meta?.field) return filter.meta.field; const queryConfig = filter.query.match_phrase ?? filter.query.match ?? {}; return Object.keys(queryConfig)[0]; }; diff --git a/packages/kbn-es-query/src/filters/build_filters/range_filter.ts b/packages/kbn-es-query/src/filters/build_filters/range_filter.ts index 2ff43a854da23a..e9bafade964b71 100644 --- a/packages/kbn-es-query/src/filters/build_filters/range_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/range_filter.ts @@ -47,7 +47,7 @@ export interface RangeFilterParams { format?: string; } -const hasRangeKeys = (params: RangeFilterParams) => +export const hasRangeKeys = (params: RangeFilterParams) => Boolean( keys(params).find((key: string) => ['gte', 'gt', 'lte', 'lt', 'from', 'to'].includes(key)) ); @@ -108,8 +108,8 @@ export const isScriptedRangeFilter = (filter: Filter): filter is ScriptedRangeFi /** * @internal */ -export const getRangeFilterField = (filter: RangeFilter) => { - return filter.query.range && Object.keys(filter.query.range)[0]; +export const getRangeFilterField = (filter: RangeFilter | ScriptedRangeFilter) => { + return filter.meta?.field ?? (filter.query.range && Object.keys(filter.query.range)[0]); }; const formatValue = (params: any[]) => diff --git a/src/plugins/data/common/es_query/stubs/phrase_filter.ts b/src/plugins/data/common/es_query/stubs/phrase_filter.ts index 8c951b4d5d1fc5..ef15d14750f9e6 100644 --- a/src/plugins/data/common/es_query/stubs/phrase_filter.ts +++ b/src/plugins/data/common/es_query/stubs/phrase_filter.ts @@ -24,5 +24,9 @@ export const phraseFilter: PhraseFilter = { $state: { store: FilterStateStore.APP_STATE, }, - query: {}, + query: { + match_phrase: { + 'machine.os': 'ios', + }, + }, }; diff --git a/src/plugins/data/common/es_query/stubs/range_filter.ts b/src/plugins/data/common/es_query/stubs/range_filter.ts index 26c26afe8f545c..a3799588b19f12 100644 --- a/src/plugins/data/common/es_query/stubs/range_filter.ts +++ b/src/plugins/data/common/es_query/stubs/range_filter.ts @@ -25,5 +25,5 @@ export const rangeFilter: RangeFilter = { $state: { store: FilterStateStore.APP_STATE, }, - query: { range: {} }, + query: { range: { bytes: { gt: 0, lt: 10 } } }, }; diff --git a/src/plugins/data/common/index.ts b/src/plugins/data/common/index.ts index 1a929df039ec06..f76b6b903fe95b 100644 --- a/src/plugins/data/common/index.ts +++ b/src/plugins/data/common/index.ts @@ -33,7 +33,6 @@ export type { SavedQuery, SavedQueryAttributes, SavedQueryTimeFilter, - FilterValueFormatter, KbnFieldTypeOptions, Query, } from './types'; diff --git a/src/plugins/data/common/types.ts b/src/plugins/data/common/types.ts index 81b47735d8fe2e..84c8f8b5a3fe1e 100644 --- a/src/plugins/data/common/types.ts +++ b/src/plugins/data/common/types.ts @@ -20,9 +20,3 @@ export * from './kbn_field_types/types'; * not possible. */ export type GetConfigFn = (key: string, defaultOverride?: T) => T; - -type FilterFormatterFunction = (value: any) => string; -export interface FilterValueFormatter { - convert: FilterFormatterFunction; - getConverterFor: (type: string) => FilterFormatterFunction; -} diff --git a/src/plugins/data/public/query/filter_manager/lib/get_display_value.test.ts b/src/plugins/data/public/query/filter_manager/lib/get_display_value.test.ts index ffa8cb533bc5e7..d32323d4d0b23f 100644 --- a/src/plugins/data/public/query/filter_manager/lib/get_display_value.test.ts +++ b/src/plugins/data/public/query/filter_manager/lib/get_display_value.test.ts @@ -7,7 +7,12 @@ */ import type { DataView } from '@kbn/data-views-plugin/public'; import { FilterStateStore, PhraseFilter } from '@kbn/es-query'; -import { stubIndexPattern, phraseFilter } from '../../../../common/stubs'; +import { + stubIndexPattern, + phraseFilter, + phrasesFilter, + rangeFilter, +} from '../../../../common/stubs'; import { getDisplayValueFromFilter, getFieldDisplayValueFromFilter } from './get_display_value'; import { FieldFormat } from '@kbn/field-formats-plugin/common'; @@ -17,38 +22,57 @@ describe('getDisplayValueFromFilter', () => { }); it('returns the value if string', () => { - phraseFilter.meta.value = 'abc'; - const displayValue = getDisplayValueFromFilter(phraseFilter, [stubIndexPattern]); + const filter = { ...phraseFilter, meta: { ...phraseFilter.meta, value: 'abc' } }; + const displayValue = getDisplayValueFromFilter(filter, [stubIndexPattern]); expect(displayValue).toBe('abc'); }); it('returns the value if undefined', () => { - phraseFilter.meta.value = undefined; - const displayValue = getDisplayValueFromFilter(phraseFilter, [stubIndexPattern]); + const filter = { + ...phraseFilter, + meta: { ...phraseFilter.meta, value: undefined, params: { query: undefined } }, + }; + const displayValue = getDisplayValueFromFilter(filter, [stubIndexPattern]); expect(displayValue).toBe(''); }); - it('calls the value function if provided', () => { - // The type of value currently doesn't match how it's used. Refactor needed. - phraseFilter.meta.value = jest.fn((x) => { - return 'abc'; - }) as any; + it('phrase filters without formatter', () => { jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => undefined!); const displayValue = getDisplayValueFromFilter(phraseFilter, [stubIndexPattern]); - expect(displayValue).toBe('abc'); - expect(phraseFilter.meta.value).toHaveBeenCalledWith(undefined); + expect(displayValue).toBe('ios'); }); - it('calls the value function if provided, with formatter', () => { + it('phrase filters with formatter', () => { const mockFormatter = new (FieldFormat.from((value: string) => 'banana' + value))(); jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => mockFormatter); - phraseFilter.meta.value = jest.fn((x) => { - return x.convert('abc'); - }) as any; const displayValue = getDisplayValueFromFilter(phraseFilter, [stubIndexPattern]); - expect(stubIndexPattern.getFormatterForField).toHaveBeenCalledTimes(1); - expect(phraseFilter.meta.value).toHaveBeenCalledWith(mockFormatter); - expect(displayValue).toBe('bananaabc'); + expect(displayValue).toBe('bananaios'); + }); + + it('phrases filters without formatter', () => { + jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => undefined!); + const displayValue = getDisplayValueFromFilter(phrasesFilter, [stubIndexPattern]); + expect(displayValue).toBe('win xp, osx'); + }); + + it('phrases filters with formatter', () => { + const mockFormatter = new (FieldFormat.from((value: string) => 'banana' + value))(); + jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => mockFormatter); + const displayValue = getDisplayValueFromFilter(phrasesFilter, [stubIndexPattern]); + expect(displayValue).toBe('bananawin xp, bananaosx'); + }); + + it('range filters without formatter', () => { + jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => undefined!); + const displayValue = getDisplayValueFromFilter(rangeFilter, [stubIndexPattern]); + expect(displayValue).toBe('0 to 10'); + }); + + it('range filters with formatter', () => { + const mockFormatter = new (FieldFormat.from((value: string) => 'banana' + value))(); + jest.spyOn(stubIndexPattern, 'getFormatterForField').mockImplementation(() => mockFormatter); + const displayValue = getDisplayValueFromFilter(rangeFilter, [stubIndexPattern]); + expect(displayValue).toBe('banana0 to banana10'); }); }); diff --git a/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts b/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts index 40bbe9a89c9926..5543e0071b4d09 100644 --- a/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts +++ b/src/plugins/data/public/query/filter_manager/lib/get_display_value.ts @@ -8,7 +8,18 @@ import { i18n } from '@kbn/i18n'; import { DataView, DataViewField } from '@kbn/data-views-plugin/public'; -import { Filter } from '@kbn/es-query'; +import { + Filter, + isPhraseFilter, + isPhrasesFilter, + isRangeFilter, + isScriptedPhraseFilter, + isScriptedRangeFilter, + getFilterField, +} from '@kbn/es-query'; +import { getPhraseDisplayValue } from './mappers/map_phrase'; +import { getPhrasesDisplayValue } from './mappers/map_phrases'; +import { getRangeDisplayValue } from './mappers/map_range'; import { getIndexPatternFromFilter } from './get_index_pattern_from_filter'; function getValueFormatter(indexPattern?: DataView, key?: string) { @@ -29,22 +40,26 @@ function getValueFormatter(indexPattern?: DataView, key?: string) { } export function getFieldDisplayValueFromFilter(filter: Filter, indexPatterns: DataView[]): string { - const { key } = filter.meta; const indexPattern = getIndexPatternFromFilter(filter, indexPatterns); if (!indexPattern) return ''; - const field = indexPattern.fields.find((f: DataViewField) => f.name === key); + + const fieldName = getFilterField(filter); + if (!fieldName) return ''; + + const field = indexPattern.fields.find((f: DataViewField) => f.name === fieldName); return field?.customLabel ?? ''; } export function getDisplayValueFromFilter(filter: Filter, indexPatterns: DataView[]): string { - const { key, value } = filter.meta; - if (typeof value === 'function') { - const indexPattern = getIndexPatternFromFilter(filter, indexPatterns); - const valueFormatter = getValueFormatter(indexPattern, key); - // TODO: distinguish between FilterMeta which is serializable to mapped FilterMeta - // Where value can be a function. - return (value as any)(valueFormatter); - } else { - return value || ''; - } + const indexPattern = getIndexPatternFromFilter(filter, indexPatterns); + const fieldName = getFilterField(filter); + const valueFormatter = getValueFormatter(indexPattern, fieldName); + + if (isPhraseFilter(filter) || isScriptedPhraseFilter(filter)) { + return getPhraseDisplayValue(filter, valueFormatter); + } else if (isPhrasesFilter(filter)) { + return getPhrasesDisplayValue(filter, valueFormatter); + } else if (isRangeFilter(filter) || isScriptedRangeFilter(filter)) { + return getRangeDisplayValue(filter, valueFormatter); + } else return filter.meta.value ?? ''; } diff --git a/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts index e7b40678816562..91b2ae8d3ada62 100644 --- a/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts +++ b/src/plugins/data/public/query/filter_manager/lib/map_and_flatten_filters.test.ts @@ -13,12 +13,6 @@ describe('filter manager utilities', () => { describe('mapAndFlattenFilters()', () => { let filters: unknown; - function getDisplayName(filter: Filter) { - return typeof filter.meta.value === 'function' - ? (filter.meta.value as any)() - : filter.meta.value; - } - beforeEach(() => { filters = [ null, @@ -51,11 +45,8 @@ describe('filter manager utilities', () => { expect(results[2].meta).toHaveProperty('key', 'query'); expect(results[2].meta).toHaveProperty('value', 'foo:bar'); expect(results[3].meta).toHaveProperty('key', 'bytes'); - expect(results[3].meta).toHaveProperty('value'); - expect(getDisplayName(results[3])).toBe('1024 to 2048'); + expect(results[3].meta).toHaveProperty('value', { gt: 1024, lt: 2048 }); expect(results[4].meta).toHaveProperty('key', '_type'); - expect(results[4].meta).toHaveProperty('value'); - expect(getDisplayName(results[4])).toBe('apache'); }); }); }); diff --git a/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts b/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts index be94e69f74f9d2..ff9c6d47660fd8 100644 --- a/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts +++ b/src/plugins/data/public/query/filter_manager/lib/map_filter.test.ts @@ -7,27 +7,22 @@ */ import { mapFilter } from './map_filter'; -import type { Filter } from '@kbn/es-query'; +import type { Filter, PhraseFilter } from '@kbn/es-query'; +import { getDisplayValueFromFilter } from '../../..'; describe('filter manager utilities', () => { - function getDisplayName(filter: Filter) { - return typeof filter.meta.value === 'function' - ? (filter.meta.value as any)() - : filter.meta.value; - } - describe('mapFilter()', () => { test('should map query filters', async () => { const before = { meta: { index: 'logstash-*' }, query: { match: { _type: { query: 'apache', type: 'phrase' } } }, }; - const after = mapFilter(before as Filter); + const after = mapFilter(before as Filter) as PhraseFilter; expect(after).toHaveProperty('meta'); expect(after.meta).toHaveProperty('key', '_type'); expect(after.meta).toHaveProperty('value'); - expect(getDisplayName(after)).toBe('apache'); + expect(getDisplayValueFromFilter(after, [])).toBe('apache'); expect(after.meta).toHaveProperty('disabled', false); expect(after.meta).toHaveProperty('negate', false); }); @@ -42,7 +37,7 @@ describe('filter manager utilities', () => { expect(after).toHaveProperty('meta'); expect(after.meta).toHaveProperty('key', '@timestamp'); expect(after.meta).toHaveProperty('value'); - expect(getDisplayName(after)).toBe('exists'); + expect(getDisplayValueFromFilter(after, [])).toBe('exists'); expect(after.meta).toHaveProperty('disabled', false); expect(after.meta).toHaveProperty('negate', false); }); @@ -54,7 +49,7 @@ describe('filter manager utilities', () => { expect(after).toHaveProperty('meta'); expect(after.meta).toHaveProperty('key', 'query'); expect(after.meta).toHaveProperty('value'); - expect(getDisplayName(after)).toBe('{"test":{}}'); + expect(getDisplayValueFromFilter(after, [])).toBe('{"test":{}}'); expect(after.meta).toHaveProperty('disabled', false); expect(after.meta).toHaveProperty('negate', false); }); diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts index c63a8f82f1704f..88e819bb7f9a7b 100644 --- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts +++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.test.ts @@ -6,12 +6,13 @@ * Side Public License, v 1. */ -import { mapPhrase } from './map_phrase'; +import { getPhraseDisplayValue, mapPhrase } from './map_phrase'; import type { PhraseFilter, Filter } from '@kbn/es-query'; +import { FieldFormat } from '@kbn/field-formats-plugin/common'; describe('filter manager utilities', () => { describe('mapPhrase()', () => { - test('should return the key and value for matching filters', async () => { + test('should return the key for matching filters', async () => { const filter = { meta: { index: 'logstash-*' }, query: { match: { _type: { query: 'apache', type: 'phrase' } } }, @@ -19,13 +20,7 @@ describe('filter manager utilities', () => { const result = mapPhrase(filter); - expect(result).toHaveProperty('value'); expect(result).toHaveProperty('key', '_type'); - - if (result.value) { - const displayName = result.value(); - expect(displayName).toBe('apache'); - } }); test('should return undefined for none matching', async (done) => { @@ -42,4 +37,31 @@ describe('filter manager utilities', () => { } }); }); + + describe('getPhraseDisplayValue()', () => { + test('without formatter with value', () => { + const filter = { meta: { value: 'hello' } } as PhraseFilter; + const result = getPhraseDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"hello"`); + }); + + test('without formatter empty value', () => { + const filter = { meta: { value: '' } } as PhraseFilter; + const result = getPhraseDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`""`); + }); + + test('without formatter with undefined value', () => { + const filter = { meta: { params: {} } } as PhraseFilter; + const result = getPhraseDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`""`); + }); + + test('with formatter', () => { + const filter = { meta: { value: 'hello' } } as PhraseFilter; + const formatter = { convert: (val) => `formatted ${val}` } as FieldFormat; + const result = getPhraseDisplayValue(filter, formatter); + expect(result).toMatchInlineSnapshot(`"formatted hello"`); + }); + }); }); diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts index 23cae0ee852ca8..fe80db37ee36c9 100644 --- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts +++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrase.ts @@ -6,27 +6,27 @@ * Side Public License, v 1. */ +import type { Filter, PhraseFilter, ScriptedPhraseFilter } from '@kbn/es-query'; import { get } from 'lodash'; import { - PhraseFilter, getPhraseFilterValue, getPhraseFilterField, FILTERS, isScriptedPhraseFilter, - Filter, isPhraseFilter, } from '@kbn/es-query'; - -import { FilterValueFormatter } from '../../../../../common'; +import { FieldFormat } from '@kbn/field-formats-plugin/common'; const getScriptedPhraseValue = (filter: PhraseFilter) => get(filter, ['query', 'script', 'script', 'params', 'value']); -const getFormattedValueFn = (value: any) => { - return (formatter?: FilterValueFormatter) => { - return formatter ? formatter.convert(value) : value; - }; -}; +export function getPhraseDisplayValue( + filter: PhraseFilter | ScriptedPhraseFilter, + formatter?: FieldFormat +) { + const value = filter.meta.value ?? filter.meta.params.query; + return formatter?.convert(value) ?? value ?? ''; +} const getParams = (filter: PhraseFilter) => { const scriptedPhraseValue = getScriptedPhraseValue(filter); @@ -39,7 +39,6 @@ const getParams = (filter: PhraseFilter) => { key, params, type: FILTERS.PHRASE, - value: getFormattedValueFn(query), }; }; diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.test.ts new file mode 100644 index 00000000000000..4a219e23aff09c --- /dev/null +++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.test.ts @@ -0,0 +1,61 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { PhrasesFilter, Filter } from '@kbn/es-query'; +import { FILTERS } from '@kbn/es-query'; +import { getPhrasesDisplayValue, mapPhrases } from './map_phrases'; +import { FieldFormat } from '@kbn/field-formats-plugin/common'; + +describe('filter manager utilities', () => { + describe('mapPhrases()', () => { + test('should return the key and value for matching filters', async () => { + const filter = { + meta: { + type: FILTERS.PHRASES, + index: 'logstash-*', + key: '_type', + params: ['hello', 1, 'world'], + }, + } as PhrasesFilter; + + const result = mapPhrases(filter); + + expect(result).toHaveProperty('key', '_type'); + expect(result).toHaveProperty('value', ['hello', 1, 'world']); + }); + + test('should return undefined for none matching', async (done) => { + const filter = { + meta: { index: 'logstash-*' }, + query: { query_string: { query: 'foo:bar' } }, + } as Filter; + + try { + mapPhrases(filter); + } catch (e) { + expect(e).toBe(filter); + done(); + } + }); + }); + + describe('getPhrasesDisplayValue()', () => { + test('without formatter', () => { + const filter = { meta: { params: ['hello', 1, 'world'] } } as PhrasesFilter; + const result = getPhrasesDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"hello, 1, world"`); + }); + + test('with formatter', () => { + const filter = { meta: { params: ['hello', 1, 'world'] } } as PhrasesFilter; + const formatter = { convert: (val) => `formatted ${val}` } as FieldFormat; + const result = getPhrasesDisplayValue(filter, formatter); + expect(result).toMatchInlineSnapshot(`"formatted hello, formatted 1, formatted world"`); + }); + }); +}); diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts index 9ffdd3070e43a5..48ca3852e715d2 100644 --- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts +++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_phrases.ts @@ -6,19 +6,16 @@ * Side Public License, v 1. */ -import { Filter, isPhrasesFilter } from '@kbn/es-query'; +import { Filter, PhrasesFilter, isPhrasesFilter } from '@kbn/es-query'; +import { FieldFormat } from '@kbn/field-formats-plugin/common'; -import { FilterValueFormatter } from '../../../../../common'; - -const getFormattedValueFn = (params: any) => { - return (formatter?: FilterValueFormatter) => { - return params - .map((v: any) => { - return formatter ? formatter.convert(v) : v; - }) - .join(', '); - }; -}; +export function getPhrasesDisplayValue(filter: PhrasesFilter, formatter?: FieldFormat) { + return filter.meta.params + .map((v: string) => { + return formatter?.convert(v) ?? v; + }) + .join(', '); +} export const mapPhrases = (filter: Filter) => { if (!isPhrasesFilter(filter)) { @@ -30,7 +27,7 @@ export const mapPhrases = (filter: Filter) => { return { type, key, - value: getFormattedValueFn(params), + value: params, params, }; }; diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts index 3b82ee6ef0f1cd..065e3da1899990 100644 --- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts +++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { mapRange } from './map_range'; +import { getRangeDisplayValue, mapRange } from './map_range'; import { FilterMeta, RangeFilter, Filter } from '@kbn/es-query'; describe('filter manager utilities', () => { @@ -19,11 +19,7 @@ describe('filter manager utilities', () => { const result = mapRange(filter); expect(result).toHaveProperty('key', 'bytes'); - expect(result).toHaveProperty('value'); - if (result.value) { - const displayName = result.value(); - expect(displayName).toBe('1024 to 2048'); - } + expect(result).toHaveProperty('value', { gt: 1024, lt: 2048 }); }); test('should return undefined for none matching', async (done) => { @@ -41,4 +37,62 @@ describe('filter manager utilities', () => { } }); }); + + describe('getRangeDisplayValue()', () => { + test('gt & lt', () => { + const params = { gt: 10, lt: 100 }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"10 to 100"`); + }); + + test('gt & lte', () => { + const params = { gt: 20, lte: 200 }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"20 to 200"`); + }); + + test('gte & lt', () => { + const params = { gte: 'low', lt: 'high' }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"low to high"`); + }); + + test('gte & lte', () => { + const params = { gte: 40, lte: 400 }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"40 to 400"`); + }); + + test('gt', () => { + const params = { gt: 50 }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"50 to Infinity"`); + }); + + test('gte', () => { + const params = { gte: 60 }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"60 to Infinity"`); + }); + + test('lt', () => { + const params = { lt: 70 }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"-Infinity to 70"`); + }); + + test('lte', () => { + const params = { lte: 80 }; + const filter = { meta: { params } } as RangeFilter; + const result = getRangeDisplayValue(filter); + expect(result).toMatchInlineSnapshot(`"-Infinity to 80"`); + }); + }); }); diff --git a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts index c5fa5ccc899578..04eb67e7921637 100644 --- a/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts +++ b/src/plugins/data/public/query/filter_manager/lib/mappers/map_range.ts @@ -6,21 +6,27 @@ * Side Public License, v 1. */ -import { get, hasIn } from 'lodash'; -import { RangeFilter, isScriptedRangeFilter, isRangeFilter, Filter, FILTERS } from '@kbn/es-query'; - -import { FilterValueFormatter } from '../../../../../common'; - -const getFormattedValueFn = (left: any, right: any) => { - return (formatter?: FilterValueFormatter) => { - let displayValue = `${left} to ${right}`; - if (formatter) { - const convert = formatter.getConverterFor('text'); - displayValue = `${convert(left)} to ${convert(right)}`; - } - return displayValue; - }; -}; +import { get } from 'lodash'; +import { + ScriptedRangeFilter, + RangeFilter, + isScriptedRangeFilter, + isRangeFilter, + Filter, + FILTERS, +} from '@kbn/es-query'; +import { FieldFormat } from '@kbn/field-formats-plugin/common'; + +export function getRangeDisplayValue( + { meta: { params } }: RangeFilter | ScriptedRangeFilter, + formatter?: FieldFormat +) { + const left = params.gte ?? params.gt ?? -Infinity; + const right = params.lte ?? params.lt ?? Infinity; + if (!formatter) return `${left} to ${right}`; + const convert = formatter.getConverterFor('text'); + return `${convert(left)} to ${convert(right)}`; +} const getFirstRangeKey = (filter: RangeFilter) => filter.query.range && Object.keys(filter.query.range)[0]; @@ -33,15 +39,7 @@ function getParams(filter: RangeFilter) { ? get(filter.query, 'script.script.params') : getRangeByKey(filter, key); - let left = hasIn(params, 'gte') ? params.gte : params.gt; - if (left == null) left = -Infinity; - - let right = hasIn(params, 'lte') ? params.lte : params.lt; - if (right == null) right = Infinity; - - const value = getFormattedValueFn(left, right); - - return { type: FILTERS.RANGE, key, value, params }; + return { type: FILTERS.RANGE, key, value: params, params }; } export const isMapRangeFilter = (filter: any): filter is RangeFilter => diff --git a/src/plugins/discover/public/application/context/services/context_state.test.ts b/src/plugins/discover/public/application/context/services/context_state.test.ts index 2b071ad9f7fbd2..ae1916158f85e2 100644 --- a/src/plugins/discover/public/application/context/services/context_state.test.ts +++ b/src/plugins/discover/public/application/context/services/context_state.test.ts @@ -133,7 +133,7 @@ describe('Test Discover Context State', () => { "query": "jpg", }, "type": "phrase", - "value": [Function], + "value": undefined, }, "query": Object { "match_phrase": Object { @@ -157,7 +157,7 @@ describe('Test Discover Context State', () => { "query": "png", }, "type": "phrase", - "value": [Function], + "value": undefined, }, "query": Object { "match_phrase": Object { diff --git a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx index 3692b19f7e4400..32601f4590558f 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx @@ -160,9 +160,8 @@ export function FilterItem(props: FilterItemProps) { function getDataTestSubj(labelConfig: LabelOptions) { const dataTestSubjKey = filter.meta.key ? `filter-key-${filter.meta.key}` : ''; - const dataTestSubjValue = filter.meta.value - ? `filter-value-${isValidLabel(labelConfig) ? labelConfig.title : labelConfig.status}` - : ''; + const valueLabel = isValidLabel(labelConfig) ? labelConfig.title : labelConfig.status; + const dataTestSubjValue = valueLabel ? `filter-value-${valueLabel}` : ''; const dataTestSubjNegated = filter.meta.negate ? 'filter-negated' : ''; const dataTestSubjDisabled = `filter-${isDisabled(labelConfig) ? 'disabled' : 'enabled'}`; const dataTestSubjPinned = `filter-${isFilterPinned(filter) ? 'pinned' : 'unpinned'}`; From fd19ec33f7e1ea56117364bf0090a0784079d538 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Tue, 13 Sep 2022 17:33:38 +0200 Subject: [PATCH 121/144] prevent component unmout when loading (#140608) --- .../plugins/security_solution/public/hosts/pages/hosts.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx index 145b9ec56a3442..9d6687a771f363 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/hosts.tsx @@ -58,7 +58,6 @@ import { ID } from '../containers/hosts'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; import { LandingPageComponent } from '../../common/components/landing_page'; -import { Loader } from '../../common/components/loader'; import { hostNameExistsFilter } from '../../common/components/visualization_actions/utils'; /** @@ -125,7 +124,7 @@ const HostsComponent = () => { }, [dispatch] ); - const { indicesExist, indexPattern, selectedPatterns, loading } = useSourcererDataView(); + const { indicesExist, indexPattern, selectedPatterns } = useSourcererDataView(); const [filterQuery, kqlError] = useMemo( () => convertToBuildEsQuery({ @@ -175,10 +174,6 @@ const HostsComponent = () => { [containerElement, onSkipFocusBeforeEventsTable, onSkipFocusAfterEventsTable] ); - if (loading) { - return ; - } - return ( <> {indicesExist ? ( From 24d4865c786cb5e0f747e5aa1f8d83ca964e58d7 Mon Sep 17 00:00:00 2001 From: Marshall Main <55718608+marshallmain@users.noreply.github.com> Date: Tue, 13 Sep 2022 09:09:04 -0700 Subject: [PATCH 122/144] [Security Solution][Alerts] Remove legacy rules schema (#137605) * Remove legacy rules schema * Remove RulesSchema from cypress test * Fix ml rule API test mock * Fix type error * Explicitly specify undefined fields in response mocks * Fix types * Remove undefined properties so expect doesn't mess it up * Use more specific types and rename newTransformValidate * Fix types in schema tests * Review comments - explicit return types, better removeServerGeneratedProperties * Re-add deleted test with modified assertion Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../schemas/request/rule_schemas.ts | 29 +- .../schemas/response/index.ts | 2 - .../response/rules_bulk_schema.test.ts | 13 +- .../schemas/response/rules_bulk_schema.ts | 4 +- .../schemas/response/rules_schema.mocks.ts | 92 ++- .../schemas/response/rules_schema.test.ts | 705 +----------------- .../schemas/response/rules_schema.ts | 366 --------- .../type_timeline_only_schema.test.ts | 66 -- .../response/type_timeline_only_schema.ts | 21 - .../security_solution/cypress/objects/rule.ts | 16 +- .../detection_engine/rules/__mocks__/api.ts | 16 +- .../containers/detection_engine/rules/api.ts | 12 +- .../routes/__mocks__/utils.ts | 14 +- .../routes/rules/create_rules_route.ts | 4 +- .../detection_engine/routes/rules/utils.ts | 8 +- .../routes/rules/validate.test.ts | 15 +- .../detection_engine/routes/rules/validate.ts | 19 +- .../rules/get_export_by_object_ids.test.ts | 7 + .../rules/get_export_by_object_ids.ts | 6 +- .../rules/get_export_details_ndjson.ts | 4 +- .../signals/__mocks__/es_results.ts | 19 + .../lib/detection_engine/signals/types.ts | 4 +- .../group10/perform_bulk_action.ts | 4 +- .../group10/update_rules.ts | 1 + .../group10/update_rules_bulk.ts | 10 +- .../group3/create_exceptions.ts | 7 +- .../utils/get_complex_rule.ts | 6 +- .../utils/get_complex_rule_output.ts | 6 +- .../utils/get_rule.ts | 4 +- .../utils/get_simple_ml_rule_output.ts | 16 +- .../utils/get_simple_rule_output.ts | 56 +- ...simple_rule_output_with_web_hook_action.ts | 6 +- .../get_simple_rule_output_without_rule_id.ts | 6 +- .../remove_server_generated_properties.ts | 27 +- .../utils/resolve_simple_rule_output.ts | 10 +- 35 files changed, 335 insertions(+), 1266 deletions(-) delete mode 100644 x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts delete mode 100644 x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.test.ts delete mode 100644 x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.ts diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts index 46186479bf7268..08e609938938c6 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.ts @@ -284,7 +284,7 @@ const { patch: threatMatchPatchParams, response: threatMatchResponseParams, } = buildAPISchemas(threatMatchRuleParams); -export { threatMatchCreateParams }; +export { threatMatchCreateParams, threatMatchResponseParams }; const queryRuleParams = { required: { @@ -307,7 +307,7 @@ const { response: queryResponseParams, } = buildAPISchemas(queryRuleParams); -export { queryCreateParams }; +export { queryCreateParams, queryResponseParams }; const savedQueryRuleParams = { required: { @@ -332,7 +332,7 @@ const { response: savedQueryResponseParams, } = buildAPISchemas(savedQueryRuleParams); -export { savedQueryCreateParams }; +export { savedQueryCreateParams, savedQueryResponseParams }; const thresholdRuleParams = { required: { @@ -356,7 +356,7 @@ const { response: thresholdResponseParams, } = buildAPISchemas(thresholdRuleParams); -export { thresholdCreateParams }; +export { thresholdCreateParams, thresholdResponseParams }; const machineLearningRuleParams = { required: { @@ -373,7 +373,7 @@ const { response: machineLearningResponseParams, } = buildAPISchemas(machineLearningRuleParams); -export { machineLearningCreateParams }; +export { machineLearningCreateParams, machineLearningResponseParams }; const newTermsRuleParams = { required: { @@ -397,7 +397,7 @@ const { response: newTermsResponseParams, } = buildAPISchemas(newTermsRuleParams); -export { newTermsCreateParams }; +export { newTermsCreateParams, newTermsResponseParams }; // --------------------------------------- // END type specific parameter definitions @@ -503,14 +503,27 @@ const responseOptionalFields = { execution_summary: RuleExecutionSummary, }; -export const fullResponseSchema = t.intersection([ +const sharedResponseSchema = t.intersection([ baseResponseParams, - responseTypeSpecific, t.exact(t.type(responseRequiredFields)), t.exact(t.partial(responseOptionalFields)), ]); +export type SharedResponseSchema = t.TypeOf; +export const fullResponseSchema = t.intersection([sharedResponseSchema, responseTypeSpecific]); export type FullResponseSchema = t.TypeOf; +// Convenience types for type specific responses +type ResponseSchema = SharedResponseSchema & T; +export type EqlResponseSchema = ResponseSchema>; +export type ThreatMatchResponseSchema = ResponseSchema>; +export type QueryResponseSchema = ResponseSchema>; +export type SavedQueryResponseSchema = ResponseSchema>; +export type ThresholdResponseSchema = ResponseSchema>; +export type MachineLearningResponseSchema = ResponseSchema< + t.TypeOf +>; +export type NewTermsResponseSchema = ResponseSchema>; + export interface RulePreviewLogs { errors: string[]; warnings: string[]; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts index e12fbf29183029..5c934b0d2e0408 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/index.ts @@ -12,5 +12,3 @@ export * from './import_rules_schema'; export * from './prepackaged_rules_schema'; export * from './prepackaged_rules_status_schema'; export * from './rules_bulk_schema'; -export * from './rules_schema'; -export * from './type_timeline_only_schema'; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts index 00800b94747168..69e31522ef40a2 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.test.ts @@ -10,12 +10,12 @@ import { pipe } from 'fp-ts/lib/pipeable'; import type { RulesBulkSchema } from './rules_bulk_schema'; import { rulesBulkSchema } from './rules_bulk_schema'; -import type { RulesSchema } from './rules_schema'; import type { ErrorSchema } from './error_schema'; import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; import { getRulesSchemaMock } from './rules_schema.mocks'; import { getErrorSchemaMock } from './error_schema.mocks'; +import type { FullResponseSchema } from '../request'; describe('prepackaged_rule_schema', () => { test('it should validate a regular message and and error together with a uuid', () => { @@ -73,15 +73,14 @@ describe('prepackaged_rule_schema', () => { const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "type"', - 'Invalid value "undefined" supplied to "error"', - ]); + expect(getPaths(left(message.errors))).toContain( + 'Invalid value "undefined" supplied to "error"' + ); expect(message.schema).toEqual({}); }); test('it should NOT validate a type of "query" when it has extra data', () => { - const rule: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); + const rule: FullResponseSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); rule.invalid_extra_data = 'invalid_extra_data'; const payload: RulesBulkSchema = [rule]; const decoded = rulesBulkSchema.decode(payload); @@ -93,7 +92,7 @@ describe('prepackaged_rule_schema', () => { }); test('it should NOT validate a type of "query" when it has extra data next to a valid error', () => { - const rule: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); + const rule: FullResponseSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); rule.invalid_extra_data = 'invalid_extra_data'; const payload: RulesBulkSchema = [getErrorSchemaMock(), rule]; const decoded = rulesBulkSchema.decode(payload); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.ts index 57d812645ed385..65c55f356c44bf 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_bulk_schema.ts @@ -7,8 +7,8 @@ import * as t from 'io-ts'; -import { rulesSchema } from './rules_schema'; +import { fullResponseSchema } from '../request'; import { errorSchema } from './error_schema'; -export const rulesBulkSchema = t.array(t.union([rulesSchema, errorSchema])); +export const rulesBulkSchema = t.array(t.union([fullResponseSchema, errorSchema])); export type RulesBulkSchema = t.TypeOf; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks.ts index c3fbec8a6d7b31..bf6583a6855f08 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks.ts @@ -6,13 +6,19 @@ */ import { DEFAULT_INDICATOR_SOURCE_PATH } from '../../../constants'; +import type { + EqlResponseSchema, + MachineLearningResponseSchema, + QueryResponseSchema, + SavedQueryResponseSchema, + SharedResponseSchema, + ThreatMatchResponseSchema, +} from '../request'; import { getListArrayMock } from '../types/lists.mock'; -import type { RulesSchema } from './rules_schema'; - export const ANCHOR_DATE = '2020-02-20T03:57:54.037Z'; -export const getRulesSchemaMock = (anchorDate: string = ANCHOR_DATE): RulesSchema => ({ +const getResponseBaseParams = (anchorDate: string = ANCHOR_DATE): SharedResponseSchema => ({ author: [], id: '7a7065d7-6e8b-4aae-8d20-c93613dec9f9', created_at: new Date(anchorDate).toISOString(), @@ -24,45 +30,83 @@ export const getRulesSchemaMock = (anchorDate: string = ANCHOR_DATE): RulesSchem from: 'now-6m', immutable: false, name: 'Query with a rule id', - query: 'user.name: root or user.name: admin', references: ['test 1', 'test 2'], - severity: 'high', + severity: 'high' as const, severity_mapping: [], updated_by: 'elastic_kibana', tags: ['some fake tag 1', 'some fake tag 2'], to: 'now', - type: 'query', threat: [], version: 1, output_index: '.siem-signals-default', max_signals: 100, risk_score: 55, risk_score_mapping: [], - language: 'kuery', rule_id: 'query-rule-id', interval: '5m', exceptions_list: getListArrayMock(), related_integrations: [], required_fields: [], setup: '', + throttle: 'no_actions', + actions: [], + building_block_type: undefined, + note: undefined, + license: undefined, + outcome: undefined, + alias_target_id: undefined, + alias_purpose: undefined, + timeline_id: undefined, + timeline_title: undefined, + meta: undefined, + rule_name_override: undefined, + timestamp_override: undefined, + timestamp_override_fallback_disabled: undefined, + namespace: undefined, }); -export const getRulesMlSchemaMock = (anchorDate: string = ANCHOR_DATE): RulesSchema => { - const basePayload = getRulesSchemaMock(anchorDate); - const { filters, index, query, language, ...rest } = basePayload; +export const getRulesSchemaMock = (anchorDate: string = ANCHOR_DATE): QueryResponseSchema => ({ + ...getResponseBaseParams(anchorDate), + query: 'user.name: root or user.name: admin', + type: 'query', + language: 'kuery', + index: undefined, + data_view_id: undefined, + filters: undefined, + saved_id: undefined, +}); +export const getSavedQuerySchemaMock = ( + anchorDate: string = ANCHOR_DATE +): SavedQueryResponseSchema => ({ + ...getResponseBaseParams(anchorDate), + query: 'user.name: root or user.name: admin', + type: 'saved_query', + saved_id: 'save id 123', + language: 'kuery', + index: undefined, + data_view_id: undefined, + filters: undefined, +}); +export const getRulesMlSchemaMock = ( + anchorDate: string = ANCHOR_DATE +): MachineLearningResponseSchema => { return { - ...rest, + ...getResponseBaseParams(anchorDate), type: 'machine_learning', anomaly_threshold: 59, machine_learning_job_id: 'some_machine_learning_job_id', }; }; -export const getThreatMatchingSchemaMock = (anchorDate: string = ANCHOR_DATE): RulesSchema => { +export const getThreatMatchingSchemaMock = ( + anchorDate: string = ANCHOR_DATE +): ThreatMatchResponseSchema => { return { - ...getRulesSchemaMock(anchorDate), + ...getResponseBaseParams(anchorDate), type: 'threat_match', + query: 'user.name: root or user.name: admin', + language: 'kuery', threat_index: ['index-123'], threat_mapping: [{ entries: [{ field: 'host.name', type: 'mapping', value: 'host.name' }] }], threat_query: '*:*', @@ -84,6 +128,14 @@ export const getThreatMatchingSchemaMock = (anchorDate: string = ANCHOR_DATE): R }, }, ], + index: undefined, + data_view_id: undefined, + filters: undefined, + saved_id: undefined, + threat_indicator_path: undefined, + threat_language: undefined, + concurrent_searches: undefined, + items_per_search: undefined, }; }; @@ -91,7 +143,9 @@ export const getThreatMatchingSchemaMock = (anchorDate: string = ANCHOR_DATE): R * Useful for e2e backend tests where it doesn't have date time and other * server side properties attached to it. */ -export const getThreatMatchingSchemaPartialMock = (enabled = false): Partial => { +export const getThreatMatchingSchemaPartialMock = ( + enabled = false +): Partial => { return { author: [], created_by: 'elastic', @@ -160,11 +214,17 @@ export const getThreatMatchingSchemaPartialMock = (enabled = false): Partial { +export const getRulesEqlSchemaMock = (anchorDate: string = ANCHOR_DATE): EqlResponseSchema => { return { - ...getRulesSchemaMock(anchorDate), + ...getResponseBaseParams(anchorDate), language: 'eql', type: 'eql', query: 'process where true', + index: undefined, + data_view_id: undefined, + filters: undefined, + timestamp_field: undefined, + event_category_override: undefined, + tiebreaker_field: undefined, }; }; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts index bac55c85109291..0a337eb28bc1c8 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.test.ts @@ -7,35 +7,23 @@ import { left } from 'fp-ts/lib/Either'; import { pipe } from 'fp-ts/lib/pipeable'; -import type * as t from 'io-ts'; -import type { RulesSchema } from './rules_schema'; -import { - rulesSchema, - checkTypeDependents, - getDependents, - addSavedId, - addQueryFields, - addTimelineTitle, - addMlFields, - addThreatMatchFields, - addEqlFields, -} from './rules_schema'; import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; -import type { TypeAndTimelineOnly } from './type_timeline_only_schema'; import { getRulesSchemaMock, getRulesMlSchemaMock, + getSavedQuerySchemaMock, getThreatMatchingSchemaMock, getRulesEqlSchemaMock, } from './rules_schema.mocks'; -import type { ListArray } from '@kbn/securitysolution-io-ts-list-types'; +import { fullResponseSchema } from '../request'; +import type { FullResponseSchema } from '../request'; describe('rules_schema', () => { test('it should validate a type of "query" without anything extra', () => { const payload = getRulesSchemaMock(); - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); const expected = getRulesSchemaMock(); @@ -45,10 +33,10 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); + const payload: FullResponseSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.invalid_extra_data = 'invalid_extra_data'; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); @@ -57,55 +45,48 @@ describe('rules_schema', () => { }); test('it should NOT validate invalid_data for the type', () => { - const payload: Omit & { type: string } = getRulesSchemaMock(); + const payload: Omit & { type: string } = getRulesSchemaMock(); payload.type = 'invalid_data'; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "invalid_data" supplied to "type"', - ]); + expect(getPaths(left(message.errors))).toHaveLength(1); expect(message.schema).toEqual({}); }); - test('it should NOT validate a type of "query" with a saved_id together', () => { - const payload = getRulesSchemaMock(); + test('it should validate a type of "query" with a saved_id together', () => { + const payload: FullResponseSchema & { saved_id?: string } = getRulesSchemaMock(); payload.type = 'query'; payload.saved_id = 'save id 123'; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual(['invalid keys "saved_id"']); - expect(message.schema).toEqual({}); + expect(getPaths(left(message.errors))).toEqual([]); + expect(message.schema).toEqual(payload); }); test('it should validate a type of "saved_query" with a "saved_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.type = 'saved_query'; - payload.saved_id = 'save id 123'; + const payload = getSavedQuerySchemaMock(); - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); - - expected.type = 'saved_query'; - expected.saved_id = 'save id 123'; + const expected = getSavedQuerySchemaMock(); expect(getPaths(left(message.errors))).toEqual([]); expect(message.schema).toEqual(expected); }); test('it should NOT validate a type of "saved_query" without a "saved_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.type = 'saved_query'; + const payload: FullResponseSchema & { saved_id?: string } = getSavedQuerySchemaMock(); + // @ts-expect-error delete payload.saved_id; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); @@ -116,12 +97,11 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "saved_query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); - payload.type = 'saved_query'; - payload.saved_id = 'save id 123'; + const payload: FullResponseSchema & { saved_id?: string; invalid_extra_data?: string } = + getSavedQuerySchemaMock(); payload.invalid_extra_data = 'invalid_extra_data'; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); @@ -134,7 +114,7 @@ describe('rules_schema', () => { payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); const expected = getRulesSchemaMock(); @@ -146,12 +126,12 @@ describe('rules_schema', () => { }); test('it should NOT validate a type of "timeline_id" if there is "timeline_title" dependent when it has extra invalid data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); + const payload: FullResponseSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); payload.timeline_id = 'some timeline id'; payload.timeline_title = 'some timeline title'; payload.invalid_extra_data = 'invalid_extra_data'; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); @@ -159,575 +139,11 @@ describe('rules_schema', () => { expect(message.schema).toEqual({}); }); - test('it should NOT validate a type of "timeline_id" if there is NOT a "timeline_title" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_id = 'some timeline id'; - - const decoded = rulesSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "timeline_title"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "timeline_title" if there is NOT a "timeline_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_title = 'some timeline title'; - - const decoded = rulesSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "timeline_title"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_title" but there is NOT a "timeline_id"', () => { - const payload = getRulesSchemaMock(); - payload.saved_id = 'some saved id'; - payload.type = 'saved_query'; - payload.timeline_title = 'some timeline title'; - - const decoded = rulesSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "timeline_title"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_id" but there is NOT a "timeline_title"', () => { - const payload = getRulesSchemaMock(); - payload.saved_id = 'some saved id'; - payload.type = 'saved_query'; - payload.timeline_id = 'some timeline id'; - - const decoded = rulesSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "timeline_title"', - ]); - expect(message.schema).toEqual({}); - }); - - describe('checkTypeDependents', () => { - test('it should validate a type of "query" without anything extra', () => { - const payload = getRulesSchemaMock(); - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it should NOT validate invalid_data for the type', () => { - const payload: Omit & { type: string } = getRulesSchemaMock(); - payload.type = 'invalid_data'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "invalid_data" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "query" with a saved_id together', () => { - const payload = getRulesSchemaMock(); - payload.type = 'query'; - payload.saved_id = 'save id 123'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "saved_id"']); - expect(message.schema).toEqual({}); - }); - - test('it should validate a type of "saved_query" with a "saved_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.type = 'saved_query'; - payload.saved_id = 'save id 123'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); - - expected.type = 'saved_query'; - expected.saved_id = 'save id 123'; - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it should NOT validate a type of "saved_query" without a "saved_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.type = 'saved_query'; - delete payload.saved_id; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "saved_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); - payload.type = 'saved_query'; - payload.saved_id = 'save id 123'; - payload.invalid_extra_data = 'invalid_extra_data'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "invalid_extra_data"']); - expect(message.schema).toEqual({}); - }); - - test('it should validate a type of "timeline_id" if there is a "timeline_title" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_id = 'some timeline id'; - payload.timeline_title = 'some timeline title'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); - expected.timeline_id = 'some timeline id'; - expected.timeline_title = 'some timeline title'; - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it should NOT validate a type of "timeline_id" if there is "timeline_title" dependent when it has extra invalid data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); - payload.timeline_id = 'some timeline id'; - payload.timeline_title = 'some timeline title'; - payload.invalid_extra_data = 'invalid_extra_data'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "invalid_extra_data"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "timeline_id" if there is NOT a "timeline_title" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_id = 'some timeline id'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "timeline_title"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "timeline_title" if there is NOT a "timeline_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_title = 'some timeline title'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "timeline_title"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_title" but there is NOT a "timeline_id"', () => { - const payload = getRulesSchemaMock(); - payload.saved_id = 'some saved id'; - payload.type = 'saved_query'; - payload.timeline_title = 'some timeline title'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "timeline_title"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_id" but there is NOT a "timeline_title"', () => { - const payload = getRulesSchemaMock(); - payload.saved_id = 'some saved id'; - payload.type = 'saved_query'; - payload.timeline_id = 'some timeline id'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "timeline_title"', - ]); - expect(message.schema).toEqual({}); - }); - }); - - describe('getDependents', () => { - test('it should validate a type of "query" without anything extra', () => { - const payload = getRulesSchemaMock(); - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it should validate a namespace as string', () => { - const payload = { - ...getRulesSchemaMock(), - namespace: 'a namespace', - }; - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate invalid_data for the type', () => { - const payload: Omit & { type: string } = getRulesSchemaMock(); - payload.type = 'invalid_data'; - - const dependents = getDependents(payload as unknown as TypeAndTimelineOnly); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "invalid_data" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "query" with a saved_id together', () => { - const payload = getRulesSchemaMock(); - payload.type = 'query'; - payload.saved_id = 'save id 123'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "saved_id"']); - expect(message.schema).toEqual({}); - }); - - test('it should validate a type of "saved_query" with a "saved_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.type = 'saved_query'; - payload.saved_id = 'save id 123'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); - - expected.type = 'saved_query'; - expected.saved_id = 'save id 123'; - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it should NOT validate a type of "saved_query" without a "saved_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.type = 'saved_query'; - delete payload.saved_id; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "saved_id"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" when it has extra data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); - payload.type = 'saved_query'; - payload.saved_id = 'save id 123'; - payload.invalid_extra_data = 'invalid_extra_data'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "invalid_extra_data"']); - expect(message.schema).toEqual({}); - }); - - test('it should validate a type of "timeline_id" if there is a "timeline_title" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_id = 'some timeline id'; - payload.timeline_title = 'some timeline title'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); - expected.timeline_id = 'some timeline id'; - expected.timeline_title = 'some timeline title'; - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it should NOT validate a type of "timeline_id" if there is "timeline_title" dependent when it has extra invalid data', () => { - const payload: RulesSchema & { invalid_extra_data?: string } = getRulesSchemaMock(); - payload.timeline_id = 'some timeline id'; - payload.timeline_title = 'some timeline title'; - payload.invalid_extra_data = 'invalid_extra_data'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "invalid_extra_data"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "timeline_id" if there is NOT a "timeline_title" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_id = 'some timeline id'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "timeline_title"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "timeline_title" if there is NOT a "timeline_id" dependent', () => { - const payload = getRulesSchemaMock(); - payload.timeline_title = 'some timeline title'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "timeline_title"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_title" but there is NOT a "timeline_id"', () => { - const payload = getRulesSchemaMock(); - payload.saved_id = 'some saved id'; - payload.type = 'saved_query'; - payload.timeline_title = 'some timeline title'; - - const decoded = checkTypeDependents(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "timeline_title"']); - expect(message.schema).toEqual({}); - }); - - test('it should NOT validate a type of "saved_query" with a "saved_id" dependent and a "timeline_id" but there is NOT a "timeline_title"', () => { - const payload = getRulesSchemaMock(); - payload.saved_id = 'some saved id'; - payload.type = 'saved_query'; - payload.timeline_id = 'some timeline id'; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "undefined" supplied to "timeline_title"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it validates an ML rule response', () => { - const payload = getRulesMlSchemaMock(); - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesMlSchemaMock(); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it rejects a response with both ML and query properties', () => { - const payload = { - ...getRulesSchemaMock(), - ...getRulesMlSchemaMock(), - }; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual(['invalid keys "query,language"']); - expect(message.schema).toEqual({}); - }); - - test('it validates a threat_match response', () => { - const payload = getThreatMatchingSchemaMock(); - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getThreatMatchingSchemaMock(); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - - test('it rejects a response with threat_match properties but type of "query"', () => { - const payload: RulesSchema = { - ...getThreatMatchingSchemaMock(), - type: 'query', - }; - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'invalid keys "threat_index,["index-123"],threat_mapping,[{"entries":[{"field":"host.name","type":"mapping","value":"host.name"}]}],threat_query,threat_filters,[{"bool":{"must":[{"query_string":{"query":"host.name: linux","analyze_wildcard":true,"time_zone":"Zulu"}}],"filter":[],"should":[],"must_not":[]}}]"', - ]); - expect(message.schema).toEqual({}); - }); - - test('it validates an eql rule response', () => { - const payload = getRulesEqlSchemaMock(); - - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - const expected = getRulesEqlSchemaMock(); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(expected); - }); - }); - - describe('addSavedId', () => { - test('should return empty array if not given a type of "saved_query"', () => { - const emptyArray = addSavedId({ type: 'query' }); - const expected: t.Mixed[] = []; - expect(emptyArray).toEqual(expected); - }); - - test('should array of size 2 given a "saved_query"', () => { - const array = addSavedId({ type: 'saved_query' }); - expect(array.length).toEqual(2); - }); - }); - - describe('addTimelineTitle', () => { - test('should return empty array if not given a timeline_id', () => { - const emptyArray = addTimelineTitle({ type: 'query' }); - const expected: t.Mixed[] = []; - expect(emptyArray).toEqual(expected); - }); - - test('should array of size 2 given a "timeline_id" that is not null', () => { - const array = addTimelineTitle({ type: 'query', timeline_id: 'some id' }); - expect(array.length).toEqual(2); - }); - }); - - describe('addQueryFields', () => { - test('should return empty array if type is not "query"', () => { - const fields = addQueryFields({ type: 'machine_learning' }); - const expected: t.Mixed[] = []; - expect(fields).toEqual(expected); - }); - - test('should return two fields for a rule of type "query"', () => { - const fields = addQueryFields({ type: 'query' }); - expect(fields.length).toEqual(3); - }); - - test('should return two fields for a rule of type "threshold"', () => { - const fields = addQueryFields({ type: 'threshold' }); - expect(fields.length).toEqual(3); - }); - - test('should return two fields for a rule of type "saved_query"', () => { - const fields = addQueryFields({ type: 'saved_query' }); - expect(fields.length).toEqual(3); - }); - - test('should return two fields for a rule of type "threat_match"', () => { - const fields = addQueryFields({ type: 'threat_match' }); - expect(fields.length).toEqual(3); - }); - }); - - describe('addMlFields', () => { - test('should return empty array if type is not "machine_learning"', () => { - const fields = addMlFields({ type: 'query' }); - const expected: t.Mixed[] = []; - expect(fields).toEqual(expected); - }); - - test('should return two fields for a rule of type "machine_learning"', () => { - const fields = addMlFields({ type: 'machine_learning' }); - expect(fields.length).toEqual(2); - }); - }); - describe('exceptions_list', () => { test('it should validate an empty array for "exceptions_list"', () => { const payload = getRulesSchemaMock(); payload.exceptions_list = []; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); const expected = getRulesSchemaMock(); @@ -737,11 +153,11 @@ describe('rules_schema', () => { }); test('it should NOT validate when "exceptions_list" is not expected type', () => { - const payload: Omit & { + const payload: Omit & { exceptions_list?: string; } = { ...getRulesSchemaMock(), exceptions_list: 'invalid_data' }; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); @@ -750,53 +166,13 @@ describe('rules_schema', () => { ]); expect(message.schema).toEqual({}); }); - - test('it should default to empty array if "exceptions_list" is undefined ', () => { - const payload: Omit & { - exceptions_list?: ListArray; - } = getRulesSchemaMock(); - payload.exceptions_list = undefined; - - const decoded = rulesSchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual({ ...payload, exceptions_list: [] }); - }); - }); - - describe('addThreatMatchFields', () => { - test('should return empty array if type is not "threat_match"', () => { - const fields = addThreatMatchFields({ type: 'query' }); - const expected: t.Mixed[] = []; - expect(fields).toEqual(expected); - }); - - test('should return nine (9) fields for a rule of type "threat_match"', () => { - const fields = addThreatMatchFields({ type: 'threat_match' }); - expect(fields.length).toEqual(10); - }); - }); - - describe('addEqlFields', () => { - test('should return empty array if type is not "eql"', () => { - const fields = addEqlFields({ type: 'query' }); - const expected: t.Mixed[] = []; - expect(fields).toEqual(expected); - }); - - test('should return 3 fields for a rule of type "eql"', () => { - const fields = addEqlFields({ type: 'eql' }); - expect(fields.length).toEqual(6); - }); }); describe('data_view_id', () => { test('it should validate a type of "query" with "data_view_id" defined', () => { const payload = { ...getRulesSchemaMock(), data_view_id: 'logs-*' }; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); const expected = { ...getRulesSchemaMock(), data_view_id: 'logs-*' }; @@ -806,18 +182,16 @@ describe('rules_schema', () => { }); test('it should validate a type of "saved_query" with "data_view_id" defined', () => { - const payload = getRulesSchemaMock(); - payload.type = 'saved_query'; - payload.saved_id = 'save id 123'; + const payload: FullResponseSchema & { saved_id?: string; data_view_id?: string } = + getSavedQuerySchemaMock(); payload.data_view_id = 'logs-*'; - const decoded = rulesSchema.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); - const expected = getRulesSchemaMock(); + const expected: FullResponseSchema & { saved_id?: string; data_view_id?: string } = + getSavedQuerySchemaMock(); - expected.type = 'saved_query'; - expected.saved_id = 'save id 123'; expected.data_view_id = 'logs-*'; expect(getPaths(left(message.errors))).toEqual([]); @@ -827,8 +201,7 @@ describe('rules_schema', () => { test('it should validate a type of "eql" with "data_view_id" defined', () => { const payload = { ...getRulesEqlSchemaMock(), data_view_id: 'logs-*' }; - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); const expected = { ...getRulesEqlSchemaMock(), data_view_id: 'logs-*' }; @@ -840,8 +213,7 @@ describe('rules_schema', () => { test('it should validate a type of "threat_match" with "data_view_id" defined', () => { const payload = { ...getThreatMatchingSchemaMock(), data_view_id: 'logs-*' }; - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); const expected = { ...getThreatMatchingSchemaMock(), data_view_id: 'logs-*' }; @@ -853,8 +225,7 @@ describe('rules_schema', () => { test('it should NOT validate a type of "machine_learning" with "data_view_id" defined', () => { const payload = { ...getRulesMlSchemaMock(), data_view_id: 'logs-*' }; - const dependents = getDependents(payload); - const decoded = dependents.decode(payload); + const decoded = fullResponseSchema.decode(payload); const checked = exactCheck(payload, decoded); const message = pipe(checked, foldLeftRight); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts deleted file mode 100644 index 794ef71bf05362..00000000000000 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/rules_schema.ts +++ /dev/null @@ -1,366 +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 * as t from 'io-ts'; -import { isObject } from 'lodash/fp'; -import type { Either } from 'fp-ts/lib/Either'; -import { left, fold } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; - -import { - actions, - from, - machine_learning_job_id, - risk_score, - DefaultRiskScoreMappingArray, - DefaultSeverityMappingArray, - threat_index, - concurrent_searches, - items_per_search, - threat_query, - threat_filters, - threat_mapping, - threat_language, - threat_indicator_path, - threats, - type, - language, - severity, - throttle, - max_signals, -} from '@kbn/securitysolution-io-ts-alerting-types'; -import { DefaultStringArray, version } from '@kbn/securitysolution-io-ts-types'; -import { DefaultListArray } from '@kbn/securitysolution-io-ts-list-types'; - -import { isMlRule } from '../../../machine_learning/helpers'; -import { isThresholdRule } from '../../utils'; -import { RuleExecutionSummary } from '../../rule_monitoring'; -import { - anomaly_threshold, - data_view_id, - description, - enabled, - timestamp_field, - event_category_override, - tiebreaker_field, - false_positives, - id, - immutable, - index, - interval, - rule_id, - name, - output_index, - query, - references, - updated_by, - tags, - to, - created_at, - created_by, - updated_at, - saved_id, - timeline_id, - timeline_title, - threshold, - filters, - meta, - outcome, - alias_target_id, - alias_purpose, - note, - building_block_type, - license, - rule_name_override, - timestamp_override, - namespace, - RelatedIntegrationArray, - RequiredFieldArray, - SetupGuide, -} from '../common'; - -import type { TypeAndTimelineOnly } from './type_timeline_only_schema'; -import { typeAndTimelineOnlySchema } from './type_timeline_only_schema'; - -/** - * This is the required fields for the rules schema response. Put all required properties on - * this base for schemas such as create_rules, update_rules, for the correct validation of the - * output schema. - */ -export const requiredRulesSchema = t.type({ - author: DefaultStringArray, - description, - enabled, - false_positives, - from, - id, - immutable, - interval, - rule_id, - output_index, - max_signals, - risk_score, - risk_score_mapping: DefaultRiskScoreMappingArray, - name, - references, - severity, - severity_mapping: DefaultSeverityMappingArray, - updated_by, - tags, - to, - type, - threat: threats, - created_at, - updated_at, - created_by, - version, - exceptions_list: DefaultListArray, - related_integrations: RelatedIntegrationArray, - required_fields: RequiredFieldArray, - setup: SetupGuide, -}); - -export type RequiredRulesSchema = t.TypeOf; - -/** - * If you have type dependents or exclusive or situations add them here AND update the - * check_type_dependents file for whichever REST flow it is going through. - */ -export const dependentRulesSchema = t.partial({ - // All but ML - data_view_id, - - // query fields - language, - query, - - // eql only fields - timestamp_field, - event_category_override, - tiebreaker_field, - - // when type = saved_query, saved_id is required - saved_id, - - // These two are required together or not at all. - timeline_id, - timeline_title, - - // ML fields - anomaly_threshold, - machine_learning_job_id, - - // Threshold fields - threshold, - - // Threat Match fields - threat_filters, - threat_index, - threat_query, - concurrent_searches, - items_per_search, - threat_mapping, - threat_language, - threat_indicator_path, -}); - -/** - * This is the partial or optional fields for the rules schema. Put all optional - * properties on this. DO NOT PUT type dependents such as xor relationships here. - * Instead use dependentRulesSchema and check_type_dependents for how to do those. - */ -export const partialRulesSchema = t.partial({ - actions, - building_block_type, - license, - throttle, - rule_name_override, - timestamp_override, - filters, - meta, - outcome, - alias_target_id, - alias_purpose, - index, - namespace, - note, - uuid: id, // Move to 'required' post-migration - execution_summary: RuleExecutionSummary, -}); - -/** - * This is the rules schema WITHOUT typeDependents. You don't normally want to use this for a decode - */ -export const rulesWithoutTypeDependentsSchema = t.intersection([ - t.exact(dependentRulesSchema), - t.exact(partialRulesSchema), - t.exact(requiredRulesSchema), -]); -export type RulesWithoutTypeDependentsSchema = t.TypeOf; - -/** - * This is the rulesSchema you want to use for checking type dependents and all the properties - * through: rulesSchema.decode(someJSONObject) - */ -export const rulesSchema = new t.Type< - RulesWithoutTypeDependentsSchema, - RulesWithoutTypeDependentsSchema, - unknown ->( - 'RulesSchema', - (input: unknown): input is RulesWithoutTypeDependentsSchema => isObject(input), - (input): Either => { - return checkTypeDependents(input); - }, - t.identity -); - -/** - * This is the correct type you want to use for Rules that are outputted from the - * REST interface. This has all base and all optional properties merged together. - */ -export type RulesSchema = t.TypeOf; - -export const addSavedId = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed[] => { - if (typeAndTimelineOnly.type === 'saved_query') { - return [ - t.exact(t.type({ saved_id: dependentRulesSchema.props.saved_id })), - t.exact(t.partial({ data_view_id: dependentRulesSchema.props.data_view_id })), - ]; - } else { - return []; - } -}; - -export const addTimelineTitle = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed[] => { - if (typeAndTimelineOnly.timeline_id != null) { - return [ - t.exact(t.type({ timeline_title: dependentRulesSchema.props.timeline_title })), - t.exact(t.type({ timeline_id: dependentRulesSchema.props.timeline_id })), - ]; - } else { - return []; - } -}; - -export const addQueryFields = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed[] => { - if (['query', 'saved_query', 'threshold', 'threat_match'].includes(typeAndTimelineOnly.type)) { - return [ - t.exact(t.type({ query: dependentRulesSchema.props.query })), - t.exact(t.type({ language: dependentRulesSchema.props.language })), - t.exact(t.partial({ data_view_id: dependentRulesSchema.props.data_view_id })), - ]; - } else { - return []; - } -}; - -export const addMlFields = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed[] => { - if (isMlRule(typeAndTimelineOnly.type)) { - return [ - t.exact(t.type({ anomaly_threshold: dependentRulesSchema.props.anomaly_threshold })), - t.exact( - t.type({ machine_learning_job_id: dependentRulesSchema.props.machine_learning_job_id }) - ), - ]; - } else { - return []; - } -}; - -export const addThresholdFields = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed[] => { - if (isThresholdRule(typeAndTimelineOnly.type)) { - return [ - t.exact(t.type({ threshold: dependentRulesSchema.props.threshold })), - t.exact(t.partial({ saved_id: dependentRulesSchema.props.saved_id })), - t.exact(t.partial({ data_view_id: dependentRulesSchema.props.data_view_id })), - ]; - } else { - return []; - } -}; - -export const addEqlFields = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed[] => { - if (typeAndTimelineOnly.type === 'eql') { - return [ - t.exact(t.partial({ timestamp_field: dependentRulesSchema.props.timestamp_field })), - t.exact( - t.partial({ event_category_override: dependentRulesSchema.props.event_category_override }) - ), - t.exact(t.partial({ tiebreaker_field: dependentRulesSchema.props.tiebreaker_field })), - t.exact(t.type({ query: dependentRulesSchema.props.query })), - t.exact(t.type({ language: dependentRulesSchema.props.language })), - t.exact(t.partial({ data_view_id: dependentRulesSchema.props.data_view_id })), - ]; - } else { - return []; - } -}; - -export const addThreatMatchFields = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed[] => { - if (typeAndTimelineOnly.type === 'threat_match') { - return [ - t.exact(t.partial({ data_view_id: dependentRulesSchema.props.data_view_id })), - t.exact(t.type({ threat_query: dependentRulesSchema.props.threat_query })), - t.exact(t.type({ threat_index: dependentRulesSchema.props.threat_index })), - t.exact(t.type({ threat_mapping: dependentRulesSchema.props.threat_mapping })), - t.exact(t.partial({ threat_language: dependentRulesSchema.props.threat_language })), - t.exact(t.partial({ threat_filters: dependentRulesSchema.props.threat_filters })), - t.exact( - t.partial({ threat_indicator_path: dependentRulesSchema.props.threat_indicator_path }) - ), - t.exact(t.partial({ saved_id: dependentRulesSchema.props.saved_id })), - t.exact(t.partial({ concurrent_searches: dependentRulesSchema.props.concurrent_searches })), - t.exact( - t.partial({ - items_per_search: dependentRulesSchema.props.items_per_search, - }) - ), - ]; - } else { - return []; - } -}; - -export const getDependents = (typeAndTimelineOnly: TypeAndTimelineOnly): t.Mixed => { - const dependents: t.Mixed[] = [ - t.exact(requiredRulesSchema), - t.exact(partialRulesSchema), - ...addSavedId(typeAndTimelineOnly), - ...addTimelineTitle(typeAndTimelineOnly), - ...addQueryFields(typeAndTimelineOnly), - ...addMlFields(typeAndTimelineOnly), - ...addThresholdFields(typeAndTimelineOnly), - ...addEqlFields(typeAndTimelineOnly), - ...addThreatMatchFields(typeAndTimelineOnly), - ]; - - if (dependents.length > 1) { - // This unsafe cast is because t.intersection does not use an array but rather a set of - // tuples and really does not look like they expected us to ever dynamically build up - // intersections, but here we are doing that. Looking at their code, although they limit - // the array elements to 5, it looks like you have N number of intersections - const unsafeCast: [t.Mixed, t.Mixed] = dependents as [t.Mixed, t.Mixed]; - return t.intersection(unsafeCast); - } else { - // We are not allowed to call t.intersection with a single value so we return without - // it here normally. - return dependents[0]; - } -}; - -export const checkTypeDependents = (input: unknown): Either => { - const typeOnlyDecoded = typeAndTimelineOnlySchema.decode(input); - const onLeft = (errors: t.Errors): Either => left(errors); - const onRight = ( - typeAndTimelineOnly: TypeAndTimelineOnly - ): Either => { - const intersections = getDependents(typeAndTimelineOnly); - return intersections.decode(input); - }; - return pipe(typeOnlyDecoded, fold(onLeft, onRight)); -}; diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.test.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.test.ts deleted file mode 100644 index 8026d99713214e..00000000000000 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.test.ts +++ /dev/null @@ -1,66 +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 { left } from 'fp-ts/lib/Either'; -import { pipe } from 'fp-ts/lib/pipeable'; - -import type { TypeAndTimelineOnly } from './type_timeline_only_schema'; -import { typeAndTimelineOnlySchema } from './type_timeline_only_schema'; -import { exactCheck, foldLeftRight, getPaths } from '@kbn/securitysolution-io-ts-utils'; - -describe('prepackaged_rule_schema', () => { - test('it should validate a a type and timeline_id together', () => { - const payload: TypeAndTimelineOnly = { - type: 'query', - timeline_id: 'some id', - }; - const decoded = typeAndTimelineOnlySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate just a type without a timeline_id of type query', () => { - const payload: TypeAndTimelineOnly = { - type: 'query', - }; - const decoded = typeAndTimelineOnlySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should validate just a type of saved_query', () => { - const payload: TypeAndTimelineOnly = { - type: 'saved_query', - }; - const decoded = typeAndTimelineOnlySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([]); - expect(message.schema).toEqual(payload); - }); - - test('it should NOT validate an invalid type', () => { - const payload: Omit & { type: string } = { - type: 'some other type', - }; - const decoded = typeAndTimelineOnlySchema.decode(payload); - const checked = exactCheck(payload, decoded); - const message = pipe(checked, foldLeftRight); - - expect(getPaths(left(message.errors))).toEqual([ - 'Invalid value "some other type" supplied to "type"', - ]); - expect(message.schema).toEqual({}); - }); -}); diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.ts deleted file mode 100644 index b164ab9b44e4fd..00000000000000 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/response/type_timeline_only_schema.ts +++ /dev/null @@ -1,21 +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 * as t from 'io-ts'; - -import { type } from '@kbn/securitysolution-io-ts-alerting-types'; -import { timeline_id } from '../common/schemas'; - -/** - * Special schema type that is only the type and the timeline_id. - * This is used for dependent type checking only. - */ -export const typeAndTimelineOnlySchema = t.intersection([ - t.exact(t.type({ type })), - t.exact(t.partial({ timeline_id })), -]); -export type TypeAndTimelineOnly = t.TypeOf; diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index 0a5d5170473fb3..6b0051f12bc298 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -5,11 +5,11 @@ * 2.0. */ -import type { RulesSchema } from '../../common/detection_engine/schemas/response'; import { rawRules } from '../../server/lib/detection_engine/rules/prepackaged_rules'; import { getMockThreatData } from '../../public/detections/mitre/mitre_tactics_techniques'; import type { CompleteTimeline } from './timeline'; import { getTimeline, getIndicatorMatchTimelineTemplate } from './timeline'; +import type { FullResponseSchema } from '../../common/detection_engine/schemas/request'; export const totalNumberOfPrebuiltRules = rawRules.length; @@ -488,7 +488,9 @@ export const getEditedRule = (): CustomRule => ({ tags: [...getExistingRule().tags, 'edited'], }); -export const expectedExportedRule = (ruleResponse: Cypress.Response): string => { +export const expectedExportedRule = ( + ruleResponse: Cypress.Response +): string => { const { id, updated_at: updatedAt, @@ -498,14 +500,20 @@ export const expectedExportedRule = (ruleResponse: Cypress.Response name, risk_score: riskScore, severity, - query, tags, timeline_id: timelineId, timeline_title: timelineTitle, } = ruleResponse.body; + let query: string | undefined; + if (ruleResponse.body.type === 'query') { + query = ruleResponse.body.query; + } + // NOTE: Order of the properties in this object matters for the tests to work. - const rule: RulesSchema = { + // TODO: Follow up https://github.com/elastic/kibana/pull/137628 and add an explicit type to this object + // without using Partial + const rule: Partial = { id, updated_at: updatedAt, updated_by: updatedBy, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts index 69aa2a4502bc03..e445e5b935af2a 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts @@ -5,10 +5,8 @@ * 2.0. */ -import type { - GetInstalledIntegrationsResponse, - RulesSchema, -} from '../../../../../../common/detection_engine/schemas/response'; +import type { FullResponseSchema } from '../../../../../../common/detection_engine/schemas/request'; +import type { GetInstalledIntegrationsResponse } from '../../../../../../common/detection_engine/schemas/response'; import { getRulesSchemaMock } from '../../../../../../common/detection_engine/schemas/response/rules_schema.mocks'; import { savedRuleMock, rulesMock } from '../mock'; @@ -25,14 +23,16 @@ import type { FetchRulesProps, } from '../types'; -export const updateRule = async ({ rule, signal }: UpdateRulesProps): Promise => +export const updateRule = async ({ rule, signal }: UpdateRulesProps): Promise => Promise.resolve(getRulesSchemaMock()); -export const createRule = async ({ rule, signal }: CreateRulesProps): Promise => +export const createRule = async ({ rule, signal }: CreateRulesProps): Promise => Promise.resolve(getRulesSchemaMock()); -export const patchRule = async ({ ruleProperties, signal }: PatchRuleProps): Promise => - Promise.resolve(getRulesSchemaMock()); +export const patchRule = async ({ + ruleProperties, + signal, +}: PatchRuleProps): Promise => Promise.resolve(getRulesSchemaMock()); export const getPrePackagedRulesStatus = async ({ signal, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts index f2e78eeee99ef3..63754adc5e7c80 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts @@ -25,7 +25,6 @@ import type { PreviewResponse, } from '../../../../../common/detection_engine/schemas/request'; import type { - RulesSchema, GetInstalledIntegrationsResponse, RulesReferencedByExceptionListsSchema, } from '../../../../../common/detection_engine/schemas/response'; @@ -74,8 +73,8 @@ export const createRule = async ({ rule, signal }: CreateRulesProps): Promise => - KibanaServices.get().http.fetch(DETECTION_ENGINE_RULES_URL, { +export const updateRule = async ({ rule, signal }: UpdateRulesProps): Promise => + KibanaServices.get().http.fetch(DETECTION_ENGINE_RULES_URL, { method: 'PUT', body: JSON.stringify(rule), signal, @@ -92,8 +91,11 @@ export const updateRule = async ({ rule, signal }: UpdateRulesProps): Promise => - KibanaServices.get().http.fetch(DETECTION_ENGINE_RULES_URL, { +export const patchRule = async ({ + ruleProperties, + signal, +}: PatchRuleProps): Promise => + KibanaServices.get().http.fetch(DETECTION_ENGINE_RULES_URL, { method: 'PATCH', body: JSON.stringify(ruleProperties), signal, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts index ccd0eb5c80fe6b..f949e927ec0957 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts @@ -8,9 +8,9 @@ import { Readable } from 'stream'; import type { HapiReadableStream } from '../../rules/types'; -import type { RulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock'; import { getThreatMock } from '../../../../../common/detection_engine/schemas/types/threat.mock'; +import type { FullResponseSchema } from '../../../../../common/detection_engine/schemas/request'; /** * Given a string, builds a hapi stream as our @@ -34,10 +34,7 @@ export const buildHapiStream = (string: string, filename = 'file.ndjson'): HapiR return stream; }; -export const getOutputRuleAlertForRest = (): Omit< - RulesSchema, - 'machine_learning_job_id' | 'anomaly_threshold' -> => ({ +export const getOutputRuleAlertForRest = (): FullResponseSchema => ({ author: ['Elastic'], actions: [], building_block_type: 'default', @@ -93,4 +90,11 @@ export const getOutputRuleAlertForRest = (): Omit< related_integrations: [], required_fields: [], setup: '', + outcome: undefined, + alias_target_id: undefined, + alias_purpose: undefined, + timestamp_override: undefined, + timestamp_override_fallback_disabled: undefined, + namespace: undefined, + data_view_id: undefined, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts index c5009138b40789..6e76de5aa420dc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.ts @@ -16,7 +16,7 @@ import { readRules } from '../../rules/read_rules'; import { buildSiemResponse } from '../utils'; import { createRulesSchema } from '../../../../../common/detection_engine/schemas/request'; -import { newTransformValidate } from './validate'; +import { transformValidate } from './validate'; import { createRuleValidateTypeDependents } from '../../../../../common/detection_engine/schemas/request/create_rules_type_dependents'; import { createRules } from '../../rules/create_rules'; import { checkDefaultRuleExceptionListReferences } from './utils/check_for_default_rule_exception_list'; @@ -89,7 +89,7 @@ export const createRulesRoute = ( const ruleExecutionSummary = await ruleExecutionLog.getExecutionSummary(createdRule.id); - const [validated, errors] = newTransformValidate(createdRule, ruleExecutionSummary); + const [validated, errors] = transformValidate(createdRule, ruleExecutionSummary); if (errors != null) { return siemResponse.error({ statusCode: 500, body: errors }); } else { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts index 2df4cb712ddd20..9dfd5b1efed7c0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/utils.ts @@ -14,7 +14,6 @@ import pMap from 'p-map'; import type { PartialRule, FindResult } from '@kbn/alerting-plugin/server'; import type { ActionsClient, FindActionResult } from '@kbn/actions-plugin/server'; import type { RuleExecutionSummary } from '../../../../../common/detection_engine/rule_monitoring'; -import type { RulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; import type { ImportRulesSchema } from '../../../../../common/detection_engine/schemas/request/import_rules_schema'; import type { CreateRulesBulkSchema } from '../../../../../common/detection_engine/schemas/request/create_rules_bulk_schema'; import type { RuleAlertType } from '../../rules/types'; @@ -26,6 +25,7 @@ import type { RuleParams } from '../../schemas/rule_schemas'; // eslint-disable-next-line no-restricted-imports import type { LegacyRulesActionsSavedObject } from '../../rule_actions/legacy_get_rule_actions_saved_object'; import type { RuleExecutionSummariesByRuleId } from '../../rule_monitoring'; +import type { FullResponseSchema } from '../../../../../common/detection_engine/schemas/request'; type PromiseFromStreams = ImportRulesSchema | Error; const MAX_CONCURRENT_SEARCHES = 10; @@ -92,7 +92,7 @@ export const getIdBulkError = ({ export const transformAlertsToRules = ( rules: RuleAlertType[], legacyRuleActions: Record -): Array> => { +): FullResponseSchema[] => { return rules.map((rule) => internalRuleToAPIResponse(rule, null, legacyRuleActions[rule.id])); }; @@ -104,7 +104,7 @@ export const transformFindAlerts = ( page: number; perPage: number; total: number; - data: Array>; + data: Array>; } | null => { return { page: ruleFindResults.page, @@ -121,7 +121,7 @@ export const transform = ( rule: PartialRule, ruleExecutionSummary?: RuleExecutionSummary | null, legacyRuleActions?: LegacyRulesActionsSavedObject | null -): Partial | null => { +): FullResponseSchema | null => { if (isAlertType(rule)) { return internalRuleToAPIResponse(rule, ruleExecutionSummary, legacyRuleActions); } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts index 21db7e52e4f8d8..84f693a529a68f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.test.ts @@ -7,14 +7,14 @@ import { transformValidate, transformValidateBulkError } from './validate'; import type { BulkError } from '../utils'; -import type { RulesSchema } from '../../../../../common/detection_engine/schemas/response'; import { getRuleMock } from '../__mocks__/request_responses'; import { ruleExecutionSummaryMock } from '../../../../../common/detection_engine/rule_monitoring/mocks'; import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock'; import { getThreatMock } from '../../../../../common/detection_engine/schemas/types/threat.mock'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import type { FullResponseSchema } from '../../../../../common/detection_engine/schemas/request'; -export const ruleOutput = (): RulesSchema => ({ +export const ruleOutput = (): FullResponseSchema => ({ actions: [], author: ['Elastic'], building_block_type: 'default', @@ -67,6 +67,15 @@ export const ruleOutput = (): RulesSchema => ({ related_integrations: [], required_fields: [], setup: '', + outcome: undefined, + alias_target_id: undefined, + alias_purpose: undefined, + rule_name_override: undefined, + timestamp_override: undefined, + timestamp_override_fallback_disabled: undefined, + namespace: undefined, + data_view_id: undefined, + saved_id: undefined, }); describe('validate', () => { @@ -114,7 +123,7 @@ describe('validate', () => { const rule = getRuleMock(getQueryRuleParams()); const ruleExecutionSumary = ruleExecutionSummaryMock.getSummarySucceeded(); const validatedOrError = transformValidateBulkError('rule-1', rule, ruleExecutionSumary); - const expected: RulesSchema = { + const expected: FullResponseSchema = { ...ruleOutput(), execution_summary: ruleExecutionSumary, }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts index 4183f217a61fe9..42e50db79294a8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/validate.ts @@ -11,8 +11,6 @@ import type { PartialRule } from '@kbn/alerting-plugin/server'; import type { RuleExecutionSummary } from '../../../../../common/detection_engine/rule_monitoring'; import type { FullResponseSchema } from '../../../../../common/detection_engine/schemas/request'; import { fullResponseSchema } from '../../../../../common/detection_engine/schemas/request'; -import type { RulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; -import { rulesSchema } from '../../../../../common/detection_engine/schemas/response/rules_schema'; import { isAlertType } from '../../rules/types'; import type { BulkError } from '../utils'; import { createBulkErrorObject } from '../utils'; @@ -26,19 +24,6 @@ export const transformValidate = ( rule: PartialRule, ruleExecutionSummary: RuleExecutionSummary | null, legacyRuleActions?: LegacyRulesActionsSavedObject | null -): [RulesSchema | null, string | null] => { - const transformed = transform(rule, ruleExecutionSummary, legacyRuleActions); - if (transformed == null) { - return [null, 'Internal error transforming']; - } else { - return validateNonExact(transformed, rulesSchema); - } -}; - -export const newTransformValidate = ( - rule: PartialRule, - ruleExecutionSummary: RuleExecutionSummary | null, - legacyRuleActions?: LegacyRulesActionsSavedObject | null ): [FullResponseSchema | null, string | null] => { const transformed = transform(rule, ruleExecutionSummary, legacyRuleActions); if (transformed == null) { @@ -52,10 +37,10 @@ export const transformValidateBulkError = ( ruleId: string, rule: PartialRule, ruleExecutionSummary: RuleExecutionSummary | null -): RulesSchema | BulkError => { +): FullResponseSchema | BulkError => { if (isAlertType(rule)) { const transformed = internalRuleToAPIResponse(rule, ruleExecutionSummary); - const [validated, errors] = validateNonExact(transformed, rulesSchema); + const [validated, errors] = validateNonExact(transformed, fullResponseSchema); if (errors != null || validated == null) { return createBulkErrorObject({ ruleId, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts index 31bdfb398c18a5..4fea86a2e3395f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.test.ts @@ -213,6 +213,13 @@ describe('get_export_by_object_ids', () => { version: 1, exceptions_list: getListArrayMock(), execution_summary: undefined, + outcome: undefined, + alias_target_id: undefined, + alias_purpose: undefined, + timestamp_override: undefined, + timestamp_override_fallback_disabled: undefined, + namespace: undefined, + data_view_id: undefined, }, ], }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts index d5008c87f3b6d3..e044c8fdfd1cab 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_by_object_ids.ts @@ -11,7 +11,6 @@ import { transformDataToNdjson } from '@kbn/securitysolution-utils'; import type { Logger } from '@kbn/core/server'; import type { ExceptionListClient } from '@kbn/lists-plugin/server'; import type { RulesClient, RuleExecutorServices } from '@kbn/alerting-plugin/server'; -import type { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; import { getExportDetailsNdjson } from './get_export_details_ndjson'; @@ -22,10 +21,11 @@ import { getRuleExceptionsForExport } from './get_export_rule_exceptions'; // eslint-disable-next-line no-restricted-imports import { legacyGetBulkRuleActionsSavedObject } from '../rule_actions/legacy_get_bulk_rule_actions_saved_object'; import { internalRuleToAPIResponse } from '../schemas/rule_converters'; +import type { FullResponseSchema } from '../../../../common/detection_engine/schemas/request'; interface ExportSuccessRule { statusCode: 200; - rule: Partial; + rule: FullResponseSchema; } interface ExportFailedRule { @@ -36,7 +36,7 @@ interface ExportFailedRule { export interface RulesErrors { exportedCount: number; missingRules: Array<{ rule_id: string }>; - rules: Array>; + rules: FullResponseSchema[]; } export const getExportByObjectIds = async ( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts index 30be45f5eb163c..204d78f5fe7d2a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/get_export_details_ndjson.ts @@ -6,12 +6,12 @@ */ import type { ExportExceptionDetails } from '@kbn/securitysolution-io-ts-list-types'; +import type { FullResponseSchema } from '../../../../common/detection_engine/schemas/request'; import type { ExportRulesDetails } from '../../../../common/detection_engine/schemas/response/export_rules_details_schema'; -import type { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; export const getExportDetailsNdjson = ( - rules: Array>, + rules: FullResponseSchema[], missingRules: Array<{ rule_id: string }> = [], exceptionDetails?: ExportExceptionDetails ): string => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts index 6c7d5d581ce613..d3cdcd82b49893 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts @@ -497,6 +497,25 @@ export const sampleSignalHit = (): SignalHit => ({ related_integrations: [], required_fields: [], setup: '', + throttle: 'no_actions', + actions: [], + building_block_type: undefined, + note: undefined, + license: undefined, + outcome: undefined, + alias_target_id: undefined, + alias_purpose: undefined, + timeline_id: undefined, + timeline_title: undefined, + meta: undefined, + rule_name_override: undefined, + timestamp_override: undefined, + timestamp_override_fallback_disabled: undefined, + namespace: undefined, + index: undefined, + data_view_id: undefined, + filters: undefined, + saved_id: undefined, }, depth: 1, }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts index db88284bc88810..5609eed4c0801f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts @@ -19,7 +19,6 @@ import type { ListClient } from '@kbn/lists-plugin/server'; import type { EcsFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/ecs_field_map'; import type { TypeOfFieldMap } from '@kbn/rule-registry-plugin/common/field_map'; import type { Status } from '../../../../common/detection_engine/schemas/common/schemas'; -import type { RulesSchema } from '../../../../common/detection_engine/schemas/response/rules_schema'; import type { BaseHit, RuleAlertAction, @@ -42,6 +41,7 @@ import type { WrappedFieldsLatest, } from '../../../../common/detection_engine/schemas/alerts'; import type { IRuleExecutionLogForExecutors } from '../rule_monitoring'; +import type { FullResponseSchema } from '../../../../common/detection_engine/schemas/request'; export interface ThresholdResult { terms?: Array<{ @@ -192,7 +192,7 @@ export interface Signal { _meta?: { version: number; }; - rule: RulesSchema; + rule: FullResponseSchema; /** * @deprecated Use "parents" instead of "parent" */ diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts index 4d4bda5e6b4e0d..c7e49ac77e7be5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/perform_bulk_action.ts @@ -18,7 +18,7 @@ import { BulkAction, BulkActionEditType, } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request/perform_bulk_action_schema'; -import { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response'; +import type { FullResponseSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { binaryToString, @@ -375,7 +375,7 @@ export default ({ getService }: FtrProviderContext): void => { expect(rulesResponse.total).to.eql(2); - rulesResponse.data.forEach((rule: RulesSchema) => { + rulesResponse.data.forEach((rule: FullResponseSchema) => { expect(rule.actions).to.eql([ { action_type_id: '.slack', diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts index 49c1ba045d5e65..1b9dcb5da28fdd 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules.ts @@ -82,6 +82,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputRule = getSimpleMlRuleOutput(); + // @ts-expect-error type narrowing is lost due to Omit<> outputRule.machine_learning_job_id = ['legacy_job_id']; outputRule.version = 2; const bodyToCompare = removeServerGeneratedProperties(body); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts index 19447dec2b4a8b..dc7209b9f1c984 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/update_rules_bulk.ts @@ -19,8 +19,6 @@ import { deleteSignalsIndex, getSimpleRuleOutput, removeServerGeneratedProperties, - getSimpleRuleOutputWithoutRuleId, - removeServerGeneratedPropertiesIncludingRuleId, getSimpleRuleUpdate, createRule, getSimpleRule, @@ -282,16 +280,16 @@ export default ({ getService }: FtrProviderContext) => { .send([updatedRule1, updatedRule2]) .expect(200); - const outputRule1 = getSimpleRuleOutputWithoutRuleId('rule-1'); + const outputRule1 = getSimpleRuleOutput('rule-1'); outputRule1.name = 'some other name'; outputRule1.version = 2; - const outputRule2 = getSimpleRuleOutputWithoutRuleId('rule-2'); + const outputRule2 = getSimpleRuleOutput('rule-2'); outputRule2.name = 'some other name'; outputRule2.version = 2; - const bodyToCompare1 = removeServerGeneratedPropertiesIncludingRuleId(body[0]); - const bodyToCompare2 = removeServerGeneratedPropertiesIncludingRuleId(body[1]); + const bodyToCompare1 = removeServerGeneratedProperties(body[0]); + const bodyToCompare2 = removeServerGeneratedProperties(body[1]); expect(bodyToCompare1).to.eql(outputRule1); expect(bodyToCompare2).to.eql(outputRule2); }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/create_exceptions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/create_exceptions.ts index f44e72f5cd50a9..647c4dddb2bb13 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/create_exceptions.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/create_exceptions.ts @@ -10,7 +10,7 @@ import expect from '@kbn/expect'; import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; -import { +import type { CreateRulesSchema, EqlCreateSchema, QueryCreateSchema, @@ -18,7 +18,6 @@ import { ThresholdCreateSchema, } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock'; -import { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response'; import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock'; import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; @@ -106,7 +105,7 @@ export default ({ getService }: FtrProviderContext) => { }; const rule = await createRule(supertest, log, ruleWithException); - const expected: Partial = { + const expected = { ...getSimpleRuleOutput(), exceptions_list: [ { @@ -147,7 +146,7 @@ export default ({ getService }: FtrProviderContext) => { await waitForRuleSuccessOrStatus(supertest, log, rule.id); const bodyToCompare = removeServerGeneratedProperties(rule); - const expected: Partial = { + const expected = { ...getSimpleRuleOutput(), enabled: true, exceptions_list: [ diff --git a/x-pack/test/detection_engine_api_integration/utils/get_complex_rule.ts b/x-pack/test/detection_engine_api_integration/utils/get_complex_rule.ts index 1db5c784660fc4..4f5cfdcd3ba566 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_complex_rule.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_complex_rule.ts @@ -5,13 +5,13 @@ * 2.0. */ -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; +import type { CreateRulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; /** * This will return a complex rule with all the outputs possible * @param ruleId The ruleId to set which is optional and defaults to rule-1 */ -export const getComplexRule = (ruleId = 'rule-1'): Partial => ({ +export const getComplexRule = (ruleId = 'rule-1'): CreateRulesSchema => ({ actions: [], author: [], name: 'Complex Rule Query', @@ -92,4 +92,6 @@ export const getComplexRule = (ruleId = 'rule-1'): Partial => ({ note: '# some investigation documentation', version: 1, query: 'user.name: root or user.name: admin', + throttle: 'no_actions', + exceptions_list: [], }); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_complex_rule_output.ts b/x-pack/test/detection_engine_api_integration/utils/get_complex_rule_output.ts index cc33c2ebff4472..1491829b339999 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_complex_rule_output.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_complex_rule_output.ts @@ -5,13 +5,15 @@ * 2.0. */ -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; +import type { FullResponseSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; +// TODO: Follow up https://github.com/elastic/kibana/pull/137628 and add an explicit type to this object +// without using Partial /** * This will return a complex rule with all the outputs possible * @param ruleId The ruleId to set which is optional and defaults to rule-1 */ -export const getComplexRuleOutput = (ruleId = 'rule-1'): Partial => ({ +export const getComplexRuleOutput = (ruleId = 'rule-1'): Partial => ({ actions: [], author: [], created_by: 'elastic', diff --git a/x-pack/test/detection_engine_api_integration/utils/get_rule.ts b/x-pack/test/detection_engine_api_integration/utils/get_rule.ts index da28e867bc9761..b1036e1f8b6821 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_rule.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_rule.ts @@ -7,7 +7,7 @@ import type { ToolingLog } from '@kbn/tooling-log'; import type SuperTest from 'supertest'; -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; +import type { FullResponseSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; @@ -21,7 +21,7 @@ export const getRule = async ( supertest: SuperTest.SuperTest, log: ToolingLog, ruleId: string -): Promise => { +): Promise => { const response = await supertest .get(`${DETECTION_ENGINE_RULES_URL}?rule_id=${ruleId}`) .set('kbn-xsrf', 'true'); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_ml_rule_output.ts b/x-pack/test/detection_engine_api_integration/utils/get_simple_ml_rule_output.ts index c845c0d343261d..56afa355b0482c 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_simple_ml_rule_output.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_simple_ml_rule_output.ts @@ -5,15 +5,13 @@ * 2.0. */ -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; -import { getSimpleRuleOutput } from './get_simple_rule_output'; - -export const getSimpleMlRuleOutput = (ruleId = 'rule-1'): Partial => { - const rule = getSimpleRuleOutput(ruleId); - const { query, language, index, ...rest } = rule; +import type { MachineLearningResponseSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; +import { getMockSharedResponseSchema } from './get_simple_rule_output'; +import { removeServerGeneratedProperties } from './remove_server_generated_properties'; +const getBaseMlRuleOutput = (ruleId = 'rule-1'): MachineLearningResponseSchema => { return { - ...rest, + ...getMockSharedResponseSchema(ruleId), name: 'Simple ML Rule', description: 'Simple Machine Learning Rule', anomaly_threshold: 44, @@ -21,3 +19,7 @@ export const getSimpleMlRuleOutput = (ruleId = 'rule-1'): Partial = type: 'machine_learning', }; }; + +export const getSimpleMlRuleOutput = (ruleId = 'rule-1') => { + return removeServerGeneratedProperties(getBaseMlRuleOutput(ruleId)); +}; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output.ts b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output.ts index 0d6cf9905d4a23..1fe2f2adecc799 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output.ts @@ -5,13 +5,16 @@ * 2.0. */ -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; +import type { + FullResponseSchema, + SharedResponseSchema, +} from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; +import { removeServerGeneratedProperties } from './remove_server_generated_properties'; -/** - * This is the typical output of a simple rule that Kibana will output with all the defaults - * except for the server generated properties. Useful for testing end to end tests. - */ -export const getSimpleRuleOutput = (ruleId = 'rule-1', enabled = false): Partial => ({ +export const getMockSharedResponseSchema = ( + ruleId = 'rule-1', + enabled = false +): SharedResponseSchema => ({ actions: [], author: [], created_by: 'elastic', @@ -20,10 +23,8 @@ export const getSimpleRuleOutput = (ruleId = 'rule-1', enabled = false): Partial false_positives: [], from: 'now-6m', immutable: false, - index: ['auditbeat-*'], interval: '5m', rule_id: ruleId, - language: 'kuery', output_index: '', max_signals: 100, related_integrations: [], @@ -31,17 +32,50 @@ export const getSimpleRuleOutput = (ruleId = 'rule-1', enabled = false): Partial risk_score: 1, risk_score_mapping: [], name: 'Simple Rule Query', - query: 'user.name: root or user.name: admin', references: [], setup: '', - severity: 'high', + severity: 'high' as const, severity_mapping: [], updated_by: 'elastic', tags: [], to: 'now', - type: 'query', threat: [], throttle: 'no_actions', exceptions_list: [], version: 1, + id: 'id', + updated_at: '2020-07-08T16:36:32.377Z', + created_at: '2020-07-08T16:36:32.377Z', + building_block_type: undefined, + note: undefined, + license: undefined, + outcome: undefined, + alias_target_id: undefined, + alias_purpose: undefined, + timeline_id: undefined, + timeline_title: undefined, + meta: undefined, + rule_name_override: undefined, + timestamp_override: undefined, + timestamp_override_fallback_disabled: undefined, + namespace: undefined, }); + +const getQueryRuleOutput = (ruleId = 'rule-1', enabled = false): FullResponseSchema => ({ + ...getMockSharedResponseSchema(ruleId, enabled), + index: ['auditbeat-*'], + language: 'kuery', + query: 'user.name: root or user.name: admin', + type: 'query', + data_view_id: undefined, + filters: undefined, + saved_id: undefined, +}); + +/** + * This is the typical output of a simple rule that Kibana will output with all the defaults + * except for the server generated properties. Useful for testing end to end tests. + */ +export const getSimpleRuleOutput = (ruleId = 'rule-1', enabled = false) => { + return removeServerGeneratedProperties(getQueryRuleOutput(ruleId, enabled)); +}; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts index 45dd0bfd5d477a..c96537bfd08134 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts @@ -5,10 +5,12 @@ * 2.0. */ -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; import { getSimpleRuleOutput } from './get_simple_rule_output'; +import { RuleWithoutServerGeneratedProperties } from './remove_server_generated_properties'; -export const getSimpleRuleOutputWithWebHookAction = (actionId: string): Partial => ({ +export const getSimpleRuleOutputWithWebHookAction = ( + actionId: string +): RuleWithoutServerGeneratedProperties => ({ ...getSimpleRuleOutput(), throttle: 'rule', actions: [ diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_without_rule_id.ts b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_without_rule_id.ts index dbf94965278d6a..56b5ab66773bba 100644 --- a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_without_rule_id.ts +++ b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_without_rule_id.ts @@ -5,14 +5,16 @@ * 2.0. */ -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; import { getSimpleRuleOutput } from './get_simple_rule_output'; +import { RuleWithoutServerGeneratedProperties } from './remove_server_generated_properties'; /** * This is the typical output of a simple rule that Kibana will output with all the defaults except * for all the server generated properties such as created_by. Useful for testing end to end tests. */ -export const getSimpleRuleOutputWithoutRuleId = (ruleId = 'rule-1'): Partial => { +export const getSimpleRuleOutputWithoutRuleId = ( + ruleId = 'rule-1' +): Omit => { const rule = getSimpleRuleOutput(ruleId); const { rule_id: rId, ...ruleWithoutRuleId } = rule; return ruleWithoutRuleId; diff --git a/x-pack/test/detection_engine_api_integration/utils/remove_server_generated_properties.ts b/x-pack/test/detection_engine_api_integration/utils/remove_server_generated_properties.ts index 5f863c0e62b9b3..8d8a34bba8b796 100644 --- a/x-pack/test/detection_engine_api_integration/utils/remove_server_generated_properties.ts +++ b/x-pack/test/detection_engine_api_integration/utils/remove_server_generated_properties.ts @@ -6,6 +6,15 @@ */ import type { FullResponseSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/request'; +import { omit, pickBy } from 'lodash'; + +const serverGeneratedProperties = ['id', 'created_at', 'updated_at', 'execution_summary'] as const; + +type ServerGeneratedProperties = typeof serverGeneratedProperties[number]; +export type RuleWithoutServerGeneratedProperties = Omit< + FullResponseSchema, + ServerGeneratedProperties +>; /** * This will remove server generated properties such as date times, etc... @@ -13,14 +22,12 @@ import type { FullResponseSchema } from '@kbn/security-solution-plugin/common/de */ export const removeServerGeneratedProperties = ( rule: FullResponseSchema -): Partial => { - const { - /* eslint-disable @typescript-eslint/naming-convention */ - id, - created_at, - updated_at, - execution_summary, - ...removedProperties - } = rule; - return removedProperties; +): RuleWithoutServerGeneratedProperties => { + const removedProperties = omit(rule, serverGeneratedProperties); + + // We're only removing undefined values, so this cast correctly narrows the type + return pickBy( + removedProperties, + (value) => value !== undefined + ) as RuleWithoutServerGeneratedProperties; }; diff --git a/x-pack/test/detection_engine_api_integration/utils/resolve_simple_rule_output.ts b/x-pack/test/detection_engine_api_integration/utils/resolve_simple_rule_output.ts index 468cbdfa23aa58..4f8b24e623ac32 100644 --- a/x-pack/test/detection_engine_api_integration/utils/resolve_simple_rule_output.ts +++ b/x-pack/test/detection_engine_api_integration/utils/resolve_simple_rule_output.ts @@ -5,11 +5,9 @@ * 2.0. */ -import type { RulesSchema } from '@kbn/security-solution-plugin/common/detection_engine/schemas/response/rules_schema'; - import { getSimpleRuleOutput } from './get_simple_rule_output'; -export const resolveSimpleRuleOutput = ( - ruleId = 'rule-1', - enabled = false -): Partial => ({ outcome: 'exactMatch', ...getSimpleRuleOutput(ruleId, enabled) }); +export const resolveSimpleRuleOutput = (ruleId = 'rule-1', enabled = false) => ({ + ...getSimpleRuleOutput(ruleId, enabled), + outcome: 'exactMatch', +}); From f079550bfdbf7cccc944d86dcd9605e2b7c1bce8 Mon Sep 17 00:00:00 2001 From: Jatin Kathuria Date: Tue, 13 Sep 2022 18:11:02 +0200 Subject: [PATCH 123/144] fix: disables notes & pinned tabs for timeline templates (#140478) --- .../timelines/components/timeline/tabs_content/index.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx index 9b633b0baed7f5..407a66086805fc 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx @@ -362,11 +362,11 @@ const TabsContentComponent: React.FC = ({ data-test-subj={`timelineTabs-${TimelineTabs.notes}`} onClick={setNotesAsActiveTab} isSelected={activeTab === TimelineTabs.notes} - disabled={false} + disabled={timelineType === TimelineType.template} key={TimelineTabs.notes} > {i18n.NOTES_TAB} - {showTimeline && numberOfNotes > 0 && ( + {showTimeline && numberOfNotes > 0 && timelineType === TimelineType.default && (
{numberOfNotes}
@@ -375,11 +375,12 @@ const TabsContentComponent: React.FC = ({ {i18n.PINNED_TAB} - {showTimeline && numberOfPinnedEvents > 0 && ( + {showTimeline && numberOfPinnedEvents > 0 && timelineType === TimelineType.default && (
{numberOfPinnedEvents}
From b0cec96d38478f7dadf9c48317d2b81569c21eee Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 18:20:20 +0200 Subject: [PATCH 124/144] Update dependency cypress to v10 (main) (#133168) --- .github/CODEOWNERS | 38 +- package.json | 16 +- .../__fixtures__/cypress_report.xml | 2 +- .../add_messages_to_report.test.ts | 4 +- x-pack/plugins/apm/ftr_e2e/cypress.config.ts | 36 + x-pack/plugins/apm/ftr_e2e/cypress.json | 19 - .../power_user/feature_flag/comparison.cy.ts} | 0 .../infrastructure/generate_data.ts | 0 .../infrastructure/infrastructure_page.cy.ts} | 0 .../integration_policy.cy.ts} | 0 .../power_user/no_data_screen.cy.ts} | 0 .../power_user/rules/error_count.cy.ts} | 0 .../settings/agent_configurations.cy.ts} | 0 .../power_user/settings/custom_links.cy.ts} | 0 .../read_only_user/deep_links.cy.ts} | 0 .../read_only_user/dependencies.cy.ts} | 0 .../errors/error_details.cy.ts} | 0 .../read_only_user/errors/errors_page.cy.ts} | 0 .../read_only_user/errors/generate_data.ts | 0 .../read_only_user/home.cy.ts} | 4 + .../service_inventory/generate_data.ts | 0 .../header_filters/generate_data.ts | 0 .../header_filters/header_filters.cy.ts} | 0 .../service_inventory.cy.ts} | 0 .../aws_lambda/aws_lamba.cy.ts} | 0 .../aws_lambda/generate_data.ts | 0 .../service_overview/errors_table.cy.ts} | 0 .../service_overview/header_filters.cy.ts} | 0 .../service_overview/instances_table.cy.ts} | 0 .../service_overview/service_overview.cy.ts} | 0 .../service_overview/time_comparison.cy.ts} | 0 .../generate_span_links_data.ts | 0 .../transaction_details/span_links.cy.ts} | 0 .../transaction_details.cy.ts} | 0 .../transactions_overview.cy.ts} | 0 .../read_only_user/tutorial/tutorial.cy.ts} | 0 .../apm/ftr_e2e/cypress/plugins/index.ts | 4 +- .../apm/ftr_e2e/cypress/support/commands.ts | 37 +- .../cypress/support/{index.ts => e2e.ts} | 4 + .../apm/ftr_e2e/cypress_test_runner.ts | 7 +- .../applications/app_search/cypress.config.js | 34 + .../applications/app_search/cypress.json | 20 - .../engines.spec.ts => e2e/engines.cy.ts} | 0 .../cypress.config.js | 35 + .../enterprise_search_overview/cypress.json | 21 - .../overview.spec.ts => e2e/overview.cy.ts} | 0 .../workplace_search/cypress.config.js | 34 + .../workplace_search/cypress.json | 20 - .../overview.spec.ts => e2e/overview.cy.ts} | 0 x-pack/plugins/fleet/cypress.config.ts | 44 ++ x-pack/plugins/fleet/cypress/cypress.json | 24 - .../fleet/cypress/downloads/downloads.html | Bin 4956 -> 0 bytes .../a11y/home_page.cy.ts} | 2 +- .../agent_binary_download_source.cy.ts} | 0 .../agent_list.cy.ts} | 0 .../agent_policy.cy.ts} | 0 .../enrollment_token.cy.ts} | 0 .../fleet_agent_flyout.cy.ts} | 0 .../fleet_settings.cy.ts} | 0 .../fleet_startup.cy.ts} | 0 .../install_assets.cy.ts} | 0 .../integrations_mock.cy.ts} | 0 .../integrations_real.cy.ts} | 0 .../package_policy.cy.ts} | 0 ...vileges_fleet_all_integrations_none.cy.ts} | 0 ...vileges_fleet_all_integrations_read.cy.ts} | 0 ...vileges_fleet_none_integrations_all.cy.ts} | 0 .../cypress/support/{index.ts => e2e.ts} | 0 x-pack/plugins/fleet/cypress/tsconfig.json | 3 +- x-pack/plugins/fleet/package.json | 6 +- x-pack/plugins/fleet/tsconfig.json | 4 +- x-pack/plugins/osquery/cypress.config.ts | 42 ++ x-pack/plugins/osquery/cypress/cypress.json | 22 - .../all/add_integration.cy.ts} | 0 .../alerts.spec.ts => e2e/all/alerts.cy.ts} | 0 .../all/discover.cy.ts} | 0 .../all/edit_saved_queries.cy.ts} | 0 .../all/live_query.cy.ts} | 0 .../metrics.spec.ts => e2e/all/metrics.cy.ts} | 0 .../all/packs.spec.ts => e2e/all/packs.cy.ts} | 0 .../all/saved_queries.cy.ts} | 0 .../admin.spec.ts => e2e/roles/admin.cy.ts} | 0 .../roles/alert_test.cy.ts} | 0 .../reader.spec.ts => e2e/roles/reader.cy.ts} | 0 .../roles/t1_analyst.cy.ts} | 0 .../roles/t2_analyst.cy.ts} | 0 .../osquery/cypress/support/coverage.ts | 4 +- .../cypress/support/{index.ts => e2e.ts} | 0 x-pack/plugins/osquery/cypress/tsconfig.json | 3 +- x-pack/plugins/osquery/package.json | 4 +- x-pack/plugins/osquery/tsconfig.json | 2 + .../security_solution/cypress/README.md | 8 +- .../detection_alerts/alerts_details.cy.ts} | 0 .../event_correlation_rule.cy.ts} | 0 .../cypress/cypress.config.ts | 30 + .../security_solution/cypress/cypress.json | 12 - .../cypress/cypress_ci.config.ts | 34 + .../security_solution/cypress/cypress_ci.json | 16 - .../cases/attach_alert_to_case.cy.ts} | 0 .../cases/attach_timeline.cy.ts} | 0 .../cases/connector_options.cy.ts} | 0 .../cases/connectors.cy.ts} | 0 .../cases/creation.cy.ts} | 0 .../cases/privileges.cy.ts} | 0 .../dashboards/entity_analytics.cy.ts} | 0 .../data_sources/create_runtime_field.cy.ts} | 0 .../data_sources/sourcerer.cy.ts} | 0 .../detection_alerts/alert_flyout.cy.ts} | 0 .../detection_alerts/alerts_details.cy.ts} | 0 ...s_detection_callouts_index_outdated.cy.ts} | 0 .../building_block_alerts.cy.ts} | 0 .../changing_alert_status.cy.ts} | 0 .../detection_alerts/cti_enrichments.cy.ts} | 0 .../investigate_in_timeline.cy.ts} | 0 .../missing_privileges_callout.cy.ts} | 0 .../open_alerts_in_timeline.cy.ts} | 0 .../all_rules_read_only.cy.ts} | 0 .../detection_rules/bulk_edit_rules.cy.ts} | 0 .../detection_rules/custom_query_rule.cy.ts} | 1 + .../custom_query_rule_data_view.cy.ts} | 0 .../event_correlation_rule.cy.ts} | 0 .../detection_rules/export_rule.cy.ts} | 0 .../detection_rules/import_rules.cy.ts} | 0 .../indicator_match_rule.cy.ts} | 0 .../detection_rules/links.cy.ts} | 0 .../machine_learning_rule.cy.ts} | 0 .../detection_rules/new_terms_rule.cy.ts} | 0 .../detection_rules/override.cy.ts} | 0 .../detection_rules/prebuilt_rules.cy.ts} | 0 .../related_integrations.cy.ts} | 0 .../detection_rules/rules_selection.cy.ts} | 0 .../rules_table_auto_refresh.cy.ts} | 0 .../detection_rules/sorting.cy.ts} | 0 .../detection_rules/threshold_rule.cy.ts} | 0 .../alerts_table_flow/add_exception.cy.ts} | 0 .../exceptions/exceptions_flyout.cy.ts} | 0 .../all_exception_lists_read_only.cy.ts} | 0 .../exceptions/exceptions_table.cy.ts} | 0 .../rule_details_flow/add_exception.spec.ts | 0 .../add_exception_data_view.spect.ts | 0 .../rule_details_flow/edit_exception.spec.ts | 0 .../edit_exception_data_view.spec.ts | 0 .../rule_details_flow/read_only_view.spect.ts | 0 .../filters/pinned_filters.cy.ts} | 0 .../guided_onboarding/tour.cy.ts} | 0 .../header/navigation.cy.ts} | 0 .../header/search_bar.cy.ts} | 0 .../host_details/risk_tab.cy.ts} | 0 .../hosts/events_viewer.cy.ts} | 0 .../hosts/host_risk_tab.cy.ts} | 0 .../hosts/hosts_risk_column.cy.ts} | 0 .../hosts/inspect.cy.ts} | 0 .../ml/ml_conditional_links.cy.ts} | 0 .../network/hover_actions.cy.ts} | 0 .../network/inspect.cy.ts} | 0 .../network/overflow_items.cy.ts} | 0 .../overview/cti_link_panel.cy.ts} | 0 .../overview/overview.cy.ts} | 0 .../pagination/pagination.cy.ts} | 0 .../timeline_templates/creation.cy.ts} | 0 .../timeline_templates/export.cy.ts} | 0 .../timelines/creation.cy.ts} | 0 .../timelines/data_providers.cy.ts} | 0 .../timelines/export.cy.ts} | 0 .../timelines/fields_browser.cy.ts} | 0 .../timelines/flyout_button.cy.ts} | 0 .../timelines/full_screen.cy.ts} | 0 .../timelines/inspect.cy.ts} | 0 .../timelines/local_storage.cy.ts} | 0 .../timelines/notes_tab.cy.ts} | 0 .../timelines/open_timeline.cy.ts} | 0 .../timelines/overview.cy.tsx} | 0 .../timelines/pagination.cy.ts} | 0 .../timelines/query_tab.cy.ts} | 0 .../timelines/row_renderers.cy.ts} | 0 .../timelines/search_or_filter.cy.ts} | 0 .../timelines/toggle_column.cy.ts} | 0 .../urls/compatibility.cy.ts} | 0 .../urls/not_found.cy.ts} | 0 .../state.spec.ts => e2e/urls/state.cy.ts} | 0 .../users/inspect.cy.ts} | 0 .../users/user_details.cy.ts} | 0 .../users/users_tabs.cy.ts} | 0 .../value_lists/value_lists.cy.ts} | 0 .../cypress/support/{index.js => e2e.js} | 0 .../detection_rules/custom_query_rule.cy.ts} | 0 .../detection_rules/threshold_rule.cy.ts} | 0 .../threat_hunting/cases/import_case.cy.ts} | 0 .../timeline/import_timeline.cy.ts} | 0 x-pack/plugins/security_solution/package.json | 23 +- .../cypress/cypress.config.ts | 37 ++ .../threat_intelligence/cypress/cypress.json | 20 - .../empty_page.cy.ts} | 0 .../indicators.cy.ts} | 0 .../query_bar.spec.ts => e2e/query_bar.cy.ts} | 0 .../timeline.spec.ts => e2e/timeline.cy.ts} | 0 .../cypress/support/{index.js => e2e.js} | 0 .../plugins/threat_intelligence/package.json | 19 +- .../test/security_solution_cypress/runner.ts | 5 +- .../threat_intelligence_cypress/runner.ts | 5 +- yarn.lock | 621 +++--------------- 201 files changed, 511 insertions(+), 815 deletions(-) create mode 100644 x-pack/plugins/apm/ftr_e2e/cypress.config.ts delete mode 100644 x-pack/plugins/apm/ftr_e2e/cypress.json rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/power_user/feature_flag/comparison.spec.ts => e2e/power_user/feature_flag/comparison.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration => e2e}/power_user/infrastructure/generate_data.ts (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/power_user/infrastructure/infrastructure_page.spec.ts => e2e/power_user/infrastructure/infrastructure_page.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/power_user/integration_settings/integration_policy.spec.ts => e2e/power_user/integration_settings/integration_policy.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/power_user/no_data_screen.ts => e2e/power_user/no_data_screen.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/power_user/rules/error_count.spec.ts => e2e/power_user/rules/error_count.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/power_user/settings/agent_configurations.spec.ts => e2e/power_user/settings/agent_configurations.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/power_user/settings/custom_links.spec.ts => e2e/power_user/settings/custom_links.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/deep_links.spec.ts => e2e/read_only_user/deep_links.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/dependencies.spec.ts => e2e/read_only_user/dependencies.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/errors/error_details.spec.ts => e2e/read_only_user/errors/error_details.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/errors/errors_page.spec.ts => e2e/read_only_user/errors/errors_page.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration => e2e}/read_only_user/errors/generate_data.ts (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/home.spec.ts => e2e/read_only_user/home.cy.ts} (95%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration => e2e}/read_only_user/service_inventory/generate_data.ts (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration => e2e}/read_only_user/service_inventory/header_filters/generate_data.ts (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_inventory/header_filters/header_filters.spec.ts => e2e/read_only_user/service_inventory/header_filters/header_filters.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_inventory/service_inventory.spec.ts => e2e/read_only_user/service_inventory/service_inventory.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_overview/aws_lambda/aws_lamba.spec.ts => e2e/read_only_user/service_overview/aws_lambda/aws_lamba.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration => e2e}/read_only_user/service_overview/aws_lambda/generate_data.ts (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_overview/errors_table.spec.ts => e2e/read_only_user/service_overview/errors_table.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_overview/header_filters.spec.ts => e2e/read_only_user/service_overview/header_filters.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_overview/instances_table.spec.ts => e2e/read_only_user/service_overview/instances_table.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_overview/service_overview.spec.ts => e2e/read_only_user/service_overview/service_overview.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/service_overview/time_comparison.spec.ts => e2e/read_only_user/service_overview/time_comparison.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration => e2e}/read_only_user/transaction_details/generate_span_links_data.ts (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/transaction_details/span_links.spec.ts => e2e/read_only_user/transaction_details/span_links.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/transaction_details/transaction_details.spec.ts => e2e/read_only_user/transaction_details/transaction_details.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/transactions_overview/transactions_overview.spec.ts => e2e/read_only_user/transactions_overview/transactions_overview.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/{integration/read_only_user/tutorial/tutorial.spec.ts => e2e/read_only_user/tutorial/tutorial.cy.ts} (100%) rename x-pack/plugins/apm/ftr_e2e/cypress/support/{index.ts => e2e.ts} (80%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/cypress.config.js delete mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/cypress.json rename x-pack/plugins/enterprise_search/public/applications/app_search/cypress/{integration/engines.spec.ts => e2e/engines.cy.ts} (100%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.config.js delete mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.json rename x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/{integration/overview.spec.ts => e2e/overview.cy.ts} (100%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.config.js delete mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.json rename x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress/{integration/overview.spec.ts => e2e/overview.cy.ts} (100%) create mode 100644 x-pack/plugins/fleet/cypress.config.ts delete mode 100644 x-pack/plugins/fleet/cypress/cypress.json delete mode 100644 x-pack/plugins/fleet/cypress/downloads/downloads.html rename x-pack/plugins/fleet/cypress/{integration/a11y/home_page.spec.ts => e2e/a11y/home_page.cy.ts} (98%) rename x-pack/plugins/fleet/cypress/{integration/agent_binary_download_source.spec.ts => e2e/agent_binary_download_source.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/agent_list.spec.ts => e2e/agent_list.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/agent_policy.spec.ts => e2e/agent_policy.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/enrollment_token.spec.ts => e2e/enrollment_token.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/fleet_agent_flyout.spec.ts => e2e/fleet_agent_flyout.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/fleet_settings.spec.ts => e2e/fleet_settings.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/fleet_startup.spec.ts => e2e/fleet_startup.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/install_assets.spec.ts => e2e/install_assets.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/integrations_mock.spec.ts => e2e/integrations_mock.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/integrations_real.spec.ts => e2e/integrations_real.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/package_policy.spec.ts => e2e/package_policy.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/privileges_fleet_all_integrations_none.spec.ts => e2e/privileges_fleet_all_integrations_none.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/privileges_fleet_all_integrations_read.spec.ts => e2e/privileges_fleet_all_integrations_read.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/{integration/privileges_fleet_none_integrations_all.spec.ts => e2e/privileges_fleet_none_integrations_all.cy.ts} (100%) rename x-pack/plugins/fleet/cypress/support/{index.ts => e2e.ts} (100%) create mode 100644 x-pack/plugins/osquery/cypress.config.ts delete mode 100644 x-pack/plugins/osquery/cypress/cypress.json rename x-pack/plugins/osquery/cypress/{integration/all/add_integration.spec.ts => e2e/all/add_integration.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/all/alerts.spec.ts => e2e/all/alerts.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/all/discover.spec.ts => e2e/all/discover.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/all/edit_saved_queries.spec.ts => e2e/all/edit_saved_queries.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/all/live_query.spec.ts => e2e/all/live_query.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/all/metrics.spec.ts => e2e/all/metrics.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/all/packs.spec.ts => e2e/all/packs.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/all/saved_queries.spec.ts => e2e/all/saved_queries.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/roles/admin.spec.ts => e2e/roles/admin.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/roles/alert_test.spec.ts => e2e/roles/alert_test.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/roles/reader.spec.ts => e2e/roles/reader.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/roles/t1_analyst.spec.ts => e2e/roles/t1_analyst.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/{integration/roles/t2_analyst.spec.ts => e2e/roles/t2_analyst.cy.ts} (100%) rename x-pack/plugins/osquery/cypress/support/{index.ts => e2e.ts} (100%) rename x-pack/plugins/security_solution/cypress/{ccs_integration/detection_alerts/alerts_details.spec.ts => ccs_e2e/detection_alerts/alerts_details.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{ccs_integration/detection_rules/event_correlation_rule.spec.ts => ccs_e2e/detection_rules/event_correlation_rule.cy.ts} (100%) create mode 100644 x-pack/plugins/security_solution/cypress/cypress.config.ts delete mode 100644 x-pack/plugins/security_solution/cypress/cypress.json create mode 100644 x-pack/plugins/security_solution/cypress/cypress_ci.config.ts delete mode 100644 x-pack/plugins/security_solution/cypress/cypress_ci.json rename x-pack/plugins/security_solution/cypress/{integration/cases/attach_alert_to_case.spec.ts => e2e/cases/attach_alert_to_case.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/cases/attach_timeline.spec.ts => e2e/cases/attach_timeline.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/cases/connector_options.spec.ts => e2e/cases/connector_options.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/cases/connectors.spec.ts => e2e/cases/connectors.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/cases/creation.spec.ts => e2e/cases/creation.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/cases/privileges.spec.ts => e2e/cases/privileges.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/dashboards/entity_analytics.spec.ts => e2e/dashboards/entity_analytics.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/data_sources/create_runtime_field.spec.ts => e2e/data_sources/create_runtime_field.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/data_sources/sourcerer.spec.ts => e2e/data_sources/sourcerer.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/alert_flyout.spec.ts => e2e/detection_alerts/alert_flyout.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/alerts_details.spec.ts => e2e/detection_alerts/alerts_details.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts => e2e/detection_alerts/alerts_detection_callouts_index_outdated.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/building_block_alerts.spec.ts => e2e/detection_alerts/building_block_alerts.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/changing_alert_status.spec.ts => e2e/detection_alerts/changing_alert_status.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/cti_enrichments.spec.ts => e2e/detection_alerts/cti_enrichments.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/investigate_in_timeline.spec.ts => e2e/detection_alerts/investigate_in_timeline.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_alerts/missing_privileges_callout.spec.ts => e2e/detection_alerts/missing_privileges_callout.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_response/open_alerts_in_timeline.spec.ts => e2e/detection_response/open_alerts_in_timeline.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/all_rules_read_only.spec.ts => e2e/detection_rules/all_rules_read_only.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/bulk_edit_rules.spec.ts => e2e/detection_rules/bulk_edit_rules.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/custom_query_rule.spec.ts => e2e/detection_rules/custom_query_rule.cy.ts} (99%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/custom_query_rule_data_view.spec.ts => e2e/detection_rules/custom_query_rule_data_view.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/event_correlation_rule.spec.ts => e2e/detection_rules/event_correlation_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/export_rule.spec.ts => e2e/detection_rules/export_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/import_rules.spec.ts => e2e/detection_rules/import_rules.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/indicator_match_rule.spec.ts => e2e/detection_rules/indicator_match_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/links.spec.ts => e2e/detection_rules/links.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/machine_learning_rule.spec.ts => e2e/detection_rules/machine_learning_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/new_terms_rule.spec.ts => e2e/detection_rules/new_terms_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/override.spec.ts => e2e/detection_rules/override.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/prebuilt_rules.spec.ts => e2e/detection_rules/prebuilt_rules.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/related_integrations.spec.ts => e2e/detection_rules/related_integrations.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/rules_selection.spec.ts => e2e/detection_rules/rules_selection.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/rules_table_auto_refresh.spec.ts => e2e/detection_rules/rules_table_auto_refresh.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/sorting.spec.ts => e2e/detection_rules/sorting.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/detection_rules/threshold_rule.spec.ts => e2e/detection_rules/threshold_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/exceptions/alerts_table_flow/add_exception.spec.ts => e2e/exceptions/alerts_table_flow/add_exception.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/exceptions/exceptions_flyout.spec.ts => e2e/exceptions/exceptions_flyout.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/exceptions/exceptions_management_flow/all_exception_lists_read_only.spec.ts => e2e/exceptions/exceptions_management_flow/all_exception_lists_read_only.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/exceptions/exceptions_table.spec.ts => e2e/exceptions/exceptions_table.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration => e2e}/exceptions/rule_details_flow/add_exception.spec.ts (100%) rename x-pack/plugins/security_solution/cypress/{integration => e2e}/exceptions/rule_details_flow/add_exception_data_view.spect.ts (100%) rename x-pack/plugins/security_solution/cypress/{integration => e2e}/exceptions/rule_details_flow/edit_exception.spec.ts (100%) rename x-pack/plugins/security_solution/cypress/{integration => e2e}/exceptions/rule_details_flow/edit_exception_data_view.spec.ts (100%) rename x-pack/plugins/security_solution/cypress/{integration => e2e}/exceptions/rule_details_flow/read_only_view.spect.ts (100%) rename x-pack/plugins/security_solution/cypress/{integration/filters/pinned_filters.spec.ts => e2e/filters/pinned_filters.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/guided_onboarding/tour.spec.ts => e2e/guided_onboarding/tour.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/header/navigation.spec.ts => e2e/header/navigation.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/header/search_bar.spec.ts => e2e/header/search_bar.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/host_details/risk_tab.spec.ts => e2e/host_details/risk_tab.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/hosts/events_viewer.spec.ts => e2e/hosts/events_viewer.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/hosts/host_risk_tab.spec.ts => e2e/hosts/host_risk_tab.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/hosts/hosts_risk_column.spec.ts => e2e/hosts/hosts_risk_column.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/hosts/inspect.spec.ts => e2e/hosts/inspect.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/ml/ml_conditional_links.spec.ts => e2e/ml/ml_conditional_links.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/network/hover_actions.spec.ts => e2e/network/hover_actions.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/network/inspect.spec.ts => e2e/network/inspect.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/network/overflow_items.spec.ts => e2e/network/overflow_items.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/overview/cti_link_panel.spec.ts => e2e/overview/cti_link_panel.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/overview/overview.spec.ts => e2e/overview/overview.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/pagination/pagination.spec.ts => e2e/pagination/pagination.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timeline_templates/creation.spec.ts => e2e/timeline_templates/creation.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timeline_templates/export.spec.ts => e2e/timeline_templates/export.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/creation.spec.ts => e2e/timelines/creation.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/data_providers.spec.ts => e2e/timelines/data_providers.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/export.spec.ts => e2e/timelines/export.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/fields_browser.spec.ts => e2e/timelines/fields_browser.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/flyout_button.spec.ts => e2e/timelines/flyout_button.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/full_screen.spec.ts => e2e/timelines/full_screen.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/inspect.spec.ts => e2e/timelines/inspect.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/local_storage.spec.ts => e2e/timelines/local_storage.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/notes_tab.spec.ts => e2e/timelines/notes_tab.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/open_timeline.spec.ts => e2e/timelines/open_timeline.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/overview.tsx => e2e/timelines/overview.cy.tsx} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/pagination.spec.ts => e2e/timelines/pagination.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/query_tab.spec.ts => e2e/timelines/query_tab.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/row_renderers.spec.ts => e2e/timelines/row_renderers.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/search_or_filter.spec.ts => e2e/timelines/search_or_filter.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/timelines/toggle_column.spec.ts => e2e/timelines/toggle_column.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/urls/compatibility.spec.ts => e2e/urls/compatibility.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/urls/not_found.spec.ts => e2e/urls/not_found.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/urls/state.spec.ts => e2e/urls/state.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/users/inspect.spec.ts => e2e/users/inspect.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/users/user_details.spec.ts => e2e/users/user_details.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/users/users_tabs.spec.ts => e2e/users/users_tabs.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{integration/value_lists/value_lists.spec.ts => e2e/value_lists/value_lists.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/support/{index.js => e2e.js} (100%) rename x-pack/plugins/security_solution/cypress/{upgrade_integration/detections/detection_rules/custom_query_rule.spec.ts => upgrade_e2e/detections/detection_rules/custom_query_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{upgrade_integration/detections/detection_rules/threshold_rule.spec.ts => upgrade_e2e/detections/detection_rules/threshold_rule.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{upgrade_integration/threat_hunting/cases/import_case.spec.ts => upgrade_e2e/threat_hunting/cases/import_case.cy.ts} (100%) rename x-pack/plugins/security_solution/cypress/{upgrade_integration/threat_hunting/timeline/import_timeline.spec.ts => upgrade_e2e/threat_hunting/timeline/import_timeline.cy.ts} (100%) create mode 100644 x-pack/plugins/threat_intelligence/cypress/cypress.config.ts delete mode 100644 x-pack/plugins/threat_intelligence/cypress/cypress.json rename x-pack/plugins/threat_intelligence/cypress/{integration/empty_page.spec.ts => e2e/empty_page.cy.ts} (100%) rename x-pack/plugins/threat_intelligence/cypress/{integration/indicators.spec.ts => e2e/indicators.cy.ts} (100%) rename x-pack/plugins/threat_intelligence/cypress/{integration/query_bar.spec.ts => e2e/query_bar.cy.ts} (100%) rename x-pack/plugins/threat_intelligence/cypress/{integration/timeline.spec.ts => e2e/timeline.cy.ts} (100%) rename x-pack/plugins/threat_intelligence/cypress/support/{index.js => e2e.js} (100%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9df9f99c02adc1..89f74e669e9cf3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -383,10 +383,10 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/security_solution/common/search_strategy/timeline @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/common/types/timeline @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/cypress/integration/timeline_templates @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/cypress/integration/timeline @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/cypress/integration/detection_alerts @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/cypress/integration/urls @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/cypress/e2e/timeline_templates @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/cypress/e2e/timeline @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/cypress/e2e/detection_alerts @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/cypress/e2e/urls @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/common/components/alerts_viewer @elastic/security-threat-hunting-investigations /x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_action @elastic/security-threat-hunting-investigations @@ -407,18 +407,18 @@ x-pack/examples/files_example @elastic/kibana-app-services /x-pack/plugins/security_solution/common/search_strategy/security_solution/network @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/common/search_strategy/security_solution/user @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/integration/cases @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/integration/host_details @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/integration/hosts @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/integration/network @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/integration/overview @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/integration/pagination @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/integration/users @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/cases @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/host_details @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/hosts @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/network @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/overview @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/pagination @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/users @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/cypress/screens/hosts @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/cypress/screens/network @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/cypress/tasks/hosts @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/cypress/tasks/network @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/cases @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/upgrade_e2e/threat_hunting/cases @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/public/common/components/charts @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/public/common/components/header_page @elastic/security-threat-hunting-explore @@ -463,7 +463,7 @@ x-pack/examples/files_example @elastic/kibana-app-services ## Security Solution sub teams - Detections and Response Rules -/x-pack/plugins/security_solution/cypress/integration/detection_rules @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/cypress/e2e/detection_rules @elastic/security-detections-response-rules /x-pack/plugins/security_solution/public/detections/components/rules @elastic/security-detections-response-rules /x-pack/plugins/security_solution/public/detections/components/severity @elastic/security-detections-response-rules @@ -488,9 +488,9 @@ x-pack/examples/files_example @elastic/kibana-app-services ## Security Solution sub teams - Security Platform /x-pack/plugins/lists @elastic/security-solution-platform -/x-pack/plugins/security_solution/cypress/integration/data_sources @elastic/security-solution-platform -/x-pack/plugins/security_solution/cypress/integration/exceptions @elastic/security-solution-platform -/x-pack/plugins/security_solution/cypress/integration/value_lists @elastic/security-solution-platform +/x-pack/plugins/security_solution/cypress/e2e/data_sources @elastic/security-solution-platform +/x-pack/plugins/security_solution/cypress/e2e/exceptions @elastic/security-solution-platform +/x-pack/plugins/security_solution/cypress/e2e/value_lists @elastic/security-solution-platform /x-pack/plugins/security_solution/public/common/components/exceptions @elastic/security-solution-platform /x-pack/plugins/security_solution/public/exceptions @elastic/security-solution-platform @@ -540,8 +540,8 @@ x-pack/plugins/security_solution/server/usage/ @elastic/security-data-analytics x-pack/plugins/security_solution/server/lib/telemetry/ @elastic/security-data-analytics ## Security Solution sub teams - security-engineering-productivity -x-pack/plugins/security_solution/cypress/ccs_integration @elastic/security-engineering-productivity -x-pack/plugins/security_solution/cypress/upgrade_integration @elastic/security-engineering-productivity +x-pack/plugins/security_solution/cypress/ccs_e2e @elastic/security-engineering-productivity +x-pack/plugins/security_solution/cypress/upgrade_e2e @elastic/security-engineering-productivity x-pack/plugins/security_solution/cypress/README.md @elastic/security-engineering-productivity x-pack/test/security_solution_cypress @elastic/security-engineering-productivity @@ -571,7 +571,7 @@ x-pack/test/threat_intelligence_cypress @elastic/protections-experience # Security Solution onboarding tour /x-pack/plugins/security_solution/public/common/components/guided_onboarding @elastic/platform-onboarding -/x-pack/plugins/security_solution/cypress/integration/guided_onboarding @elastic/platform-onboarding +/x-pack/plugins/security_solution/cypress/e2e/guided_onboarding @elastic/platform-onboarding # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design diff --git a/package.json b/package.json index 9947161017b8af..c8c1aa501b9814 100644 --- a/package.json +++ b/package.json @@ -650,9 +650,9 @@ "@babel/types": "^7.19.0", "@bazel/ibazel": "^0.16.2", "@bazel/typescript": "4.6.2", - "@cypress/code-coverage": "^3.9.12", + "@cypress/code-coverage": "^3.10.0", "@cypress/snapshot": "^2.1.7", - "@cypress/webpack-preprocessor": "^5.6.0", + "@cypress/webpack-preprocessor": "^5.12.2", "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/github-checks-reporter": "0.0.20b3", "@elastic/makelogs": "^6.0.0", @@ -1228,14 +1228,14 @@ "cssnano": "^5.1.12", "cssnano-preset-default": "^5.2.12", "csstype": "^3.0.2", - "cypress": "^9.6.1", - "cypress-axe": "^0.14.0", + "cypress": "^10.7.0", + "cypress-axe": "^1.0.0", "cypress-file-upload": "^5.0.8", - "cypress-multi-reporters": "^1.6.0", + "cypress-multi-reporters": "^1.6.1", "cypress-pipe": "^2.0.0", - "cypress-react-selector": "^2.3.17", - "cypress-real-events": "^1.7.0", - "cypress-recurse": "^1.20.0", + "cypress-react-selector": "^3.0.0", + "cypress-real-events": "^1.7.1", + "cypress-recurse": "^1.23.0", "debug": "^2.6.9", "delete-empty": "^2.0.0", "dependency-check": "^4.1.0", diff --git a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/cypress_report.xml b/packages/kbn-test/src/failed_tests_reporter/__fixtures__/cypress_report.xml index ed0e154552caac..c0c66e81db26d2 100644 --- a/packages/kbn-test/src/failed_tests_reporter/__fixtures__/cypress_report.xml +++ b/packages/kbn-test/src/failed_tests_reporter/__fixtures__/cypress_report.xml @@ -1,6 +1,6 @@ - + diff --git a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts index 220a336915bf14..3b71823ee6bdeb 100644 --- a/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts +++ b/packages/kbn-test/src/failed_tests_reporter/add_messages_to_report.test.ts @@ -282,9 +282,9 @@ it('rewrites cypress reports with minimal changes', async () => { -‹?xml version="1.0" encoding="UTF-8"?› +‹?xml version="1.0" encoding="utf-8"?› ‹testsuites name="Mocha Tests" time="16.198" tests="2" failures="1"› - - ‹testsuite name="Root Suite" timestamp="2020-07-22T15:06:26" tests="0" file="cypress/integration/timeline_flyout_button.spec.ts" failures="0" time="0"› + - ‹testsuite name="Root Suite" timestamp="2020-07-22T15:06:26" tests="0" file="cypress/e2e/timeline_flyout_button.spec.ts" failures="0" time="0"› - ‹/testsuite› - + ‹testsuite name="Root Suite" timestamp="2020-07-22T15:06:26" tests="0" file="cypress/integration/timeline_flyout_button.spec.ts" failures="0" time="0"/› + + ‹testsuite name="Root Suite" timestamp="2020-07-22T15:06:26" tests="0" file="cypress/e2e/timeline_flyout_button.spec.ts" failures="0" time="0"/› ‹testsuite name="timeline flyout button" timestamp="2020-07-22T15:06:26" tests="2" failures="1" time="16.198"› - ‹testcase name="timeline flyout button toggles open the timeline" time="8.099" classname="toggles open the timeline"› - ‹/testcase› diff --git a/x-pack/plugins/apm/ftr_e2e/cypress.config.ts b/x-pack/plugins/apm/ftr_e2e/cypress.config.ts new file mode 100644 index 00000000000000..7a92b84ac36bd4 --- /dev/null +++ b/x-pack/plugins/apm/ftr_e2e/cypress.config.ts @@ -0,0 +1,36 @@ +/* + * 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 { defineConfig } from 'cypress'; +import { plugin } from './cypress/plugins'; + +module.exports = defineConfig({ + fileServerFolder: './cypress', + fixturesFolder: './cypress/fixtures', + screenshotsFolder: './cypress/screenshots', + videosFolder: './cypress/videos', + requestTimeout: 10000, + responseTimeout: 40000, + defaultCommandTimeout: 30000, + execTimeout: 120000, + pageLoadTimeout: 120000, + viewportHeight: 900, + viewportWidth: 1440, + video: false, + screenshotOnRunFailure: false, + e2e: { + // We've imported your old cypress plugins here. + // You may want to clean this up later by importing these. + setupNodeEvents(on, config) { + plugin(on, config); + }, + baseUrl: 'http://localhost:5601', + supportFile: './cypress/support/e2e.ts', + specPattern: './cypress/e2e/**/*.cy.{js,jsx,ts,tsx}', + experimentalSessionAndOrigin: false, + }, +}); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress.json b/x-pack/plugins/apm/ftr_e2e/cypress.json deleted file mode 100644 index 848a10efed6682..00000000000000 --- a/x-pack/plugins/apm/ftr_e2e/cypress.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "fileServerFolder": "./cypress", - "fixturesFolder": "./cypress/fixtures", - "integrationFolder": "./cypress/integration", - "pluginsFile": "./cypress/plugins/index.ts", - "screenshotsFolder": "./cypress/screenshots", - "supportFile": "./cypress/support/index.ts", - "videosFolder": "./cypress/videos", - "requestTimeout": 10000, - "responseTimeout": 40000, - "defaultCommandTimeout": 30000, - "execTimeout": 120000, - "pageLoadTimeout": 120000, - "viewportHeight": 900, - "viewportWidth": 1440, - "video": false, - "screenshotOnRunFailure": false, - "experimentalSessionAndOrigin": true -} diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/feature_flag/comparison.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/feature_flag/comparison.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/feature_flag/comparison.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/feature_flag/comparison.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/infrastructure/generate_data.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/generate_data.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/infrastructure/generate_data.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/infrastructure_page.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/infrastructure/infrastructure_page.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/infrastructure/infrastructure_page.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/infrastructure/infrastructure_page.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/integration_settings/integration_policy.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/integration_settings/integration_policy.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/integration_settings/integration_policy.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/integration_settings/integration_policy.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/no_data_screen.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/no_data_screen.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/no_data_screen.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/no_data_screen.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/rules/error_count.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/rules/error_count.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/rules/error_count.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/rules/error_count.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/settings/agent_configurations.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/agent_configurations.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/settings/agent_configurations.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/custom_links.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/settings/custom_links.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/power_user/settings/custom_links.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/power_user/settings/custom_links.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/deep_links.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/deep_links.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/deep_links.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/deep_links.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/dependencies.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/dependencies.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/dependencies.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/error_details.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/error_details.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/error_details.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/error_details.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/errors_page.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/errors_page.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/errors_page.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/errors_page.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/generate_data.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/errors/generate_data.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/errors/generate_data.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/home.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/home.cy.ts similarity index 95% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/home.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/home.cy.ts index be9acfd38ab0ce..2ee2f4f019b12a 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/home.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/home.cy.ts @@ -31,6 +31,10 @@ describe('Home page', () => { to: new Date(end).getTime(), }) ); + + cy.updateAdvancedSettings({ + 'observability:enableComparisonByDefault': true, + }); }); after(() => { diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/generate_data.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/generate_data.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/generate_data.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/generate_data.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/generate_data.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/generate_data.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/header_filters.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/header_filters.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/header_filters/header_filters.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/header_filters/header_filters.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/service_inventory.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/service_inventory.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_inventory/service_inventory.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_inventory/service_inventory.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/aws_lamba.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/aws_lambda/aws_lamba.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/aws_lamba.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/aws_lambda/aws_lamba.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/aws_lambda/generate_data.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/aws_lambda/generate_data.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/aws_lambda/generate_data.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/errors_table.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/errors_table.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/errors_table.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/errors_table.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/header_filters.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/header_filters.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/header_filters.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/header_filters.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/instances_table.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/instances_table.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/instances_table.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/instances_table.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/service_overview.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/service_overview.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/time_comparison.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/time_comparison.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/time_comparison.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/time_comparison.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/generate_span_links_data.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transaction_details/generate_span_links_data.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/generate_span_links_data.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transaction_details/generate_span_links_data.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/span_links.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transaction_details/span_links.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/span_links.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transaction_details/span_links.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/transaction_details.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transaction_details/transaction_details.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transaction_details/transaction_details.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transaction_details/transaction_details.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transactions_overview/transactions_overview.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/transactions_overview/transactions_overview.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/transactions_overview/transactions_overview.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/tutorial/tutorial.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/tutorial/tutorial.cy.ts similarity index 100% rename from x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/tutorial/tutorial.spec.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/tutorial/tutorial.cy.ts diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts b/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts index 2cc7595ce67313..8adaad0b71c631 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/plugins/index.ts @@ -29,7 +29,7 @@ import { createEsClientForTesting } from '@kbn/test'; * @type {Cypress.PluginConfig} */ -const plugin: Cypress.PluginConfig = (on, config) => { +export const plugin: Cypress.PluginConfig = (on, config) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config @@ -66,5 +66,3 @@ const plugin: Cypress.PluginConfig = (on, config) => { }, }); }; - -module.exports = plugin; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts index 37182e328ebf37..692926d3049ca9 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts @@ -21,25 +21,26 @@ Cypress.Commands.add('loginAsEditorUser', () => { Cypress.Commands.add( 'loginAs', ({ username, password }: { username: string; password: string }) => { - cy.log(`Calling 'loginAs'`); - cy.session([username, password], () => { - cy.log(`Logging in as ${username}`); - const kibanaUrl = Cypress.env('KIBANA_URL'); - cy.request({ - log: false, - method: 'POST', - url: `${kibanaUrl}/internal/security/login`, - body: { - providerType: 'basic', - providerName: 'basic', - currentURL: `${kibanaUrl}/login`, - params: { username, password }, - }, - headers: { - 'kbn-xsrf': 'e2e_test', - }, - }); + // cy.session(username, () => { + const kibanaUrl = Cypress.env('KIBANA_URL'); + cy.log(`Logging in as ${username} on ${kibanaUrl}`); + cy.visit('/'); + cy.request({ + log: true, + method: 'POST', + url: `${kibanaUrl}/internal/security/login`, + body: { + providerType: 'basic', + providerName: 'basic', + currentURL: `${kibanaUrl}/login`, + params: { username, password }, + }, + headers: { + 'kbn-xsrf': 'e2e_test', + }, + // }); }); + cy.visit('/'); } ); diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/support/index.ts b/x-pack/plugins/apm/ftr_e2e/cypress/support/e2e.ts similarity index 80% rename from x-pack/plugins/apm/ftr_e2e/cypress/support/index.ts rename to x-pack/plugins/apm/ftr_e2e/cypress/support/e2e.ts index 48367848ed48f1..93daa0bc7ed2ac 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/support/index.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/support/e2e.ts @@ -5,5 +5,9 @@ * 2.0. */ +Cypress.on('uncaught:exception', (err, runnable) => { + return false; +}); + import './commands'; // import './output_command_timings'; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress_test_runner.ts b/x-pack/plugins/apm/ftr_e2e/cypress_test_runner.ts index 86316fe7ef8c82..9736a695e81c73 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress_test_runner.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress_test_runner.ts @@ -58,10 +58,9 @@ export async function cypressTestRunner({ getService }: FtrProviderContext) { ...cypressCliArgs, project: cypressProjectPath, config: { - baseUrl: kibanaUrl, - requestTimeout: 10000, - responseTimeout: 60000, - defaultCommandTimeout: 15000, + e2e: { + baseUrl: kibanaUrl, + }, }, env: { KIBANA_URL: kibanaUrl, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/cypress.config.js b/x-pack/plugins/enterprise_search/public/applications/app_search/cypress.config.js new file mode 100644 index 00000000000000..b625b3051f15a4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/cypress.config.js @@ -0,0 +1,34 @@ +/* + * 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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'cypress'; + +// eslint-disable-next-line import/no-default-export +export default defineConfig({ + defaultCommandTimeout: 120000, + e2e: { + baseUrl: 'http://localhost:5601', + // eslint-disable-next-line no-unused-vars + setupNodeEvents(on, config) {}, + supportFile: './cypress/support/commands.ts', + }, + env: { + password: 'changeme', + username: 'elastic', + }, + execTimeout: 120000, + pageLoadTimeout: 180000, + retries: { + runMode: 2, + }, + screenshotsFolder: '../../../target/cypress/screenshots', + video: false, + videosFolder: '../../../target/cypress/videos', + viewportHeight: 1200, + viewportWidth: 1600, +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/cypress.json b/x-pack/plugins/enterprise_search/public/applications/app_search/cypress.json deleted file mode 100644 index 766aaf6df36ada..00000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/cypress.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "supportFile": "./cypress/support/commands.ts", - "pluginsFile": false, - "retries": { - "runMode": 2 - }, - "baseUrl": "http://localhost:5601", - "env": { - "username": "elastic", - "password": "changeme" - }, - "screenshotsFolder": "../../../target/cypress/screenshots", - "videosFolder": "../../../target/cypress/videos", - "defaultCommandTimeout": 120000, - "execTimeout": 120000, - "pageLoadTimeout": 180000, - "viewportWidth": 1600, - "viewportHeight": 1200, - "video": false -} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/cypress/integration/engines.spec.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/cypress/e2e/engines.cy.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/cypress/integration/engines.spec.ts rename to x-pack/plugins/enterprise_search/public/applications/app_search/cypress/e2e/engines.cy.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.config.js b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.config.js new file mode 100644 index 00000000000000..a6d98df28c413c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.config.js @@ -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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'cypress'; + +// eslint-disable-next-line import/no-default-export +export default defineConfig({ + defaultCommandTimeout: 120000, + e2e: { + baseUrl: 'http://localhost:5601', + // eslint-disable-next-line no-unused-vars + setupNodeEvents(on, config) {}, + supportFile: false, + }, + env: { + password: 'changeme', + username: 'elastic', + }, + execTimeout: 120000, + fixturesFolder: false, + pageLoadTimeout: 180000, + retries: { + runMode: 2, + }, + screenshotsFolder: '../../../target/cypress/screenshots', + video: false, + videosFolder: '../../../target/cypress/videos', + viewportHeight: 1200, + viewportWidth: 1600, +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.json b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.json deleted file mode 100644 index 8ca8bdfd79a49b..00000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "supportFile": false, - "pluginsFile": false, - "retries": { - "runMode": 2 - }, - "baseUrl": "http://localhost:5601", - "env": { - "username": "elastic", - "password": "changeme" - }, - "fixturesFolder": false, - "screenshotsFolder": "../../../target/cypress/screenshots", - "videosFolder": "../../../target/cypress/videos", - "defaultCommandTimeout": 120000, - "execTimeout": 120000, - "pageLoadTimeout": 180000, - "viewportWidth": 1600, - "viewportHeight": 1200, - "video": false -} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/integration/overview.spec.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/e2e/overview.cy.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/integration/overview.spec.ts rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_overview/cypress/e2e/overview.cy.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.config.js b/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.config.js new file mode 100644 index 00000000000000..b625b3051f15a4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.config.js @@ -0,0 +1,34 @@ +/* + * 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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'cypress'; + +// eslint-disable-next-line import/no-default-export +export default defineConfig({ + defaultCommandTimeout: 120000, + e2e: { + baseUrl: 'http://localhost:5601', + // eslint-disable-next-line no-unused-vars + setupNodeEvents(on, config) {}, + supportFile: './cypress/support/commands.ts', + }, + env: { + password: 'changeme', + username: 'elastic', + }, + execTimeout: 120000, + pageLoadTimeout: 180000, + retries: { + runMode: 2, + }, + screenshotsFolder: '../../../target/cypress/screenshots', + video: false, + videosFolder: '../../../target/cypress/videos', + viewportHeight: 1200, + viewportWidth: 1600, +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.json b/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.json deleted file mode 100644 index 766aaf6df36ada..00000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "supportFile": "./cypress/support/commands.ts", - "pluginsFile": false, - "retries": { - "runMode": 2 - }, - "baseUrl": "http://localhost:5601", - "env": { - "username": "elastic", - "password": "changeme" - }, - "screenshotsFolder": "../../../target/cypress/screenshots", - "videosFolder": "../../../target/cypress/videos", - "defaultCommandTimeout": 120000, - "execTimeout": 120000, - "pageLoadTimeout": 180000, - "viewportWidth": 1600, - "viewportHeight": 1200, - "video": false -} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress/integration/overview.spec.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress/e2e/overview.cy.ts similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress/integration/overview.spec.ts rename to x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress/e2e/overview.cy.ts diff --git a/x-pack/plugins/fleet/cypress.config.ts b/x-pack/plugins/fleet/cypress.config.ts new file mode 100644 index 00000000000000..e2d5ffd3ffdac8 --- /dev/null +++ b/x-pack/plugins/fleet/cypress.config.ts @@ -0,0 +1,44 @@ +/* + * 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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'cypress'; + +// eslint-disable-next-line import/no-default-export +export default defineConfig({ + defaultCommandTimeout: 60000, + requestTimeout: 60000, + responseTimeout: 60000, + execTimeout: 120000, + pageLoadTimeout: 120000, + + retries: { + runMode: 2, + }, + + screenshotsFolder: '../../../target/kibana-fleet/cypress/screenshots', + trashAssetsBeforeRuns: false, + video: false, + videosFolder: '../../../target/kibana-fleet/cypress/videos', + viewportHeight: 900, + viewportWidth: 1440, + screenshotOnRunFailure: true, + + env: { + protocol: 'http', + hostname: 'localhost', + configport: '5601', + }, + + e2e: { + baseUrl: 'http://localhost:5601', + setupNodeEvents(on, config) { + // eslint-disable-next-line @typescript-eslint/no-var-requires, @kbn/imports/no_boundary_crossing + return require('./cypress/plugins')(on, config); + }, + }, +}); diff --git a/x-pack/plugins/fleet/cypress/cypress.json b/x-pack/plugins/fleet/cypress/cypress.json deleted file mode 100644 index b36d0c513116ce..00000000000000 --- a/x-pack/plugins/fleet/cypress/cypress.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "baseUrl": "http://localhost:5620", - "defaultCommandTimeout": 60000, - "requestTimeout": 60000, - "responseTimeout": 60000, - "execTimeout": 120000, - "pageLoadTimeout": 120000, - "nodeVersion": "system", - "retries": { - "runMode": 2 - }, - "screenshotsFolder": "../../../target/kibana-fleet/cypress/screenshots", - "trashAssetsBeforeRuns": false, - "video": false, - "videosFolder": "../../../target/kibana-fleet/cypress/videos", - "viewportHeight": 900, - "viewportWidth": 1440, - "screenshotOnRunFailure": true, - "env": { - "protocol": "http", - "hostname": "localhost", - "configport": "5601" - } -} diff --git a/x-pack/plugins/fleet/cypress/downloads/downloads.html b/x-pack/plugins/fleet/cypress/downloads/downloads.html deleted file mode 100644 index 772778ea352e58515ffdccdd56b8f8f73a6b15c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4956 zcmZ{ncQhPMzs9kwzDkrJiQapnu1*M1qeSnW6+~}~RfAQcBw1mJAX-Fp37h=1=!>W; zNc6BaYOuT9yM(MZ&s%afTO$e&Q>A@ijShd z!f<=H?XlS^EC~H%_Q5KP?7oFJ(xb$KM{a_)k#cl8Lq0Hgbc z+Zx;#mn@L8Pm|}|<`ut5W2@lbOZ^z$aO==d`SDT;3UjxG3{h~5*?-_$qshD%g{L`E zgNRDytK~u*3Yy7t<+jTTCm!$$c&@AcTsqTvBKtwm~LtS*NB_G12xX!3_Z7eXe5?^nGxg`>0pGscpEhhY%)h7Bb5vvJ&y=OT`xk*kJ`~^+j?YYwhyef@fZ7LbVsW2)|)5e!~k9j zDW^n!uTfz=KE@u_XEz|BUo#o=fa(R0x!`kXy7H~y#S%Q5{Z z9=k8Ze#o+GkLZ1<@Ksb|;I4^9KR;SRf&K1=vX!wla0{YNALQC(eQzC}=EN~#BvC)4 zz4?{2hA*hcHi^2gBOzb)qy))81|TINWlkW6w`$H^$dhH)KXt4$r2lU8)8Rzh2IafJ zM!7A@V;<=`xN!LM{RZvu3k=ZfFe!v@n2|N1I z)!eug$neEAjs)%PHN!AB+|R5Ge0rf$Bky;oFxTvy=*rb}`SB6as(tkqI;UpOoB42W z6?(tSU&@uc3`MG2@rZXG#Fg#+r>$)REabBw*5WLZHyr+1dR$Y+{vXyK^x|YV-F^$q zg{?EkD5Ur&%js{76HS~p$$CYsL>x>b5)ooL@Qg55wi{=oPD9u0_7WLMO*yrZTSyG^ zqOX3#1teuVm#l`{{DHdCu|{WfX5&HfqgeEigz>_1#Fw9mA?Pmdn&Gy}5$uOC3yL8+ya}&s;u`7BaVszCU7gT130CE-*Dk>@x zO&KbyKR?TVi~f%b2=wrTNcukV3X}?RTU%wBKMU_I-T>auG9ocEq@-d19xZ_WT%-Fl z|No%B)qe#^g?d4JLp@uI;~|z-Y=eR21!SysmJ(C_e;zpbqIP0NN?S_`tn#aQUfAT0 z3nf^lWGB38UOri_O4b-+bj2ez#5@g2_s!Z>NPYgc>%KzYF+-6ho9$AAlv@KU(*yCZ z=3u-Uu5_*wH)wf1)j+)@sxe~xd^u!a4cEh+FO>Yo&bduh_jRURo|yUF_xk_z+-1s{ zAj1o2nK4S=rTAjQ+vmaSoUaM`^k|ZuCS~~iNW!e8GS=Q;V-{{dTvBXUOOr`kN8_q! z&|H#!75H#*HY#>JRnHl1u@$}_qDZa^Mb5*BYC)lNp-EC`YVapsG{{ctjt|*M8JlH- z>MDt-0Eg*k9LcALyCssg{Rl8cUl9{q^aAjU6D?d?_CYJVI!{i1g|wRdB& z8ntMWtc_jeQ6dK=fr7|GVTxMpN;F-c@vGOBK+&J5(X=K>&1DQP0Yn!@2l8j18LtB? zGzr(DHTm?(hIlAm!{l;7w-W#oKwBQlb(rcZS01taa=)`n;%X#k#s28kd))N$g?v26 z8D`Nsio3~kKPIYC90UJQMIhev#E)`&Z^XZbI7dd|(!2`-R=C8EC=0Oos|(9ZR!_{q zP(2~p|2vjHe(~r##1r2u{BTp+vdy$GaKgC;!rxzhGJHxxl2Ol@A zp!eX?Fg1YJshcg^Al(^nnyNikM$rOOK!ZRqomH7_l6#uMk=K?CLV6(Xp3!+LY09@k z=OktZY%?}JHzQBVWtH-OTVRJuQqSo=PQR`KKO4NaVxt{G@d~UZ`Q?5AUrd#oQ-WVE zMXGFijHb#PAV@});)uEhARUz8dR>Da1d#qh_N0vaWGxO2%+NaYur&mCLd~#2Mo&Lu zH=^GGJQAi=O?PX!Z%i-rUa!90GQF*4wX616HbWMEW?^(|OSyx(o}nH2wjBkK=#~m8 zZ|A4x(h`m2C6v7K$QGPAdFiwO<;PUFHKt+4(U@_PnWeUZfIyOn#Qf_F1`d=}%_Z~@ zjhhlA94@?Y?{`!ZLft&}U)K6Lf3mj{J(nV0?HBKzGzI$U2!13VT{~!(B$RYsL{#OK z=4?dVw~?Mv;|!5b!8A^;-P7q;WXnc6@n?28-%%dGWvAl7g{`c?80}n!+29q*f;Q@< z@SFa&BiL$ZhV~c#1kjv!C%9D-G@KS1F=bZ)TpYLwv2G2P3P*Q2=-t>GyBTY^dak@M zq;?}_TtyJyT@+x^g98TU%y0FMVCUX7s{Y~{AN-Uarw%?-iP~F}9jBaWmK&$+t`1TE z>i)F!*`N}r&N!;(M)Rhpe0yb78?);00a(UsY^0*zm!kdZ=()UfC!vRi;693YW|cvI zu~Hd?dbmSGs4h3wAOh7i#20{ZzX|gG(2Gk!JPHs|dj6`0>Jrltr+}}n{OoXQ`tzhqy~MrJZ|KKwql|KR zkycyD(29YFCujtKSg;OnY08V<<84R7)eL zaSEsYokSgoMkzM_*5^y!N2pw^29;McF<;>{rh}LSiNB3;=6c_*F^av@fd#DIYD39+ zwBpX%Ay*_AWZ$WCrc1m^yYr{ht)r_im*NVi_MOC7rd!hy{>K0KBRGZ;1AC2WDCGF% zKKtQI{qd3)b}BQef>+)fzj5AIFyiiRy1+7fb>Fkc`fJGpeDDZ_h1{SobgHS0j*d4m zpp1l$SNUcci-X=OL!xRBr&a)fqKuZ*5YRx?CjxHfR{BIuB@Pe{B9Z>Htcn1?iI~~0 zQqkygDrFfUXh3ea1z|#T7g}_qV(28&0$On1wk0~NjE+yAbyWmh3`8_3aop7$)?^3C z?UYfFa{WWvOMAhXZjOe7suFm>m^2giBq{Pwq#%<*(t{}k6X`HX0M#rbtPOC?mk^b| z9_8ZnQdQ&Vv8wo0#m)G&uSZ@P?xceyhX%NB$W(2)+3s6N%uKHBZupGHtYU}1>I6mb zBG)JHE0Z~soVjbq9f0BIuYN~BV$HHMjn${n3z>#=2N&Vj_k~>$Mi?|dUoG!jI0V($YXo7Q1&)K`;TVmZ+mbss~wRE>`BePf&@2xj#`1m*Rno@hNkx zOB;c2#1B5B2Gb-uV3)w8dPqfS@WDn6uhvsp@4NQGDdeYZ@eJLK}bBf zysZ~)&L%DiMPh7st4Hh+NG09r4_mLREOoDq-9hYc#^~MG?M97mbSzWrdOS>Qx zH=L8@ch1G!j8B$Q;4erLqRl%Vw zUExboj*Ib2MRun@qUw6IYoxVi?qTaL*=f{5J{%X~lLS$Lp;0Na)r}`NT*= zB3@*Ln=Z8!(eG=%Yx=AfJS4Ym8@F7WHlA5$?A{HCR_N1bC^QN)iVs@0liry(I+vX@ zq+C?L#eXxpQ*LfJv9aELQ}))KP1P`Dj$^4&aqI2&V>{c7gUisY+$25*Y_mzqwB}%?A%+Qo;>&W*s?zCv5{yI6`W!$&IimQT41}0wSwL}oRYdu zIT-f(LrTZx3}C!toQ%vQ;&7+2!EU?DvejTj)<^V7N)ey6CQ@Z>caL_KAhAXG`aHA% zdebRpS*tgilcDP^o7~QJN;bCrb?-N`EoyZ4G?ne`0iP+whmH#h?p5J32zNqq zS4&on9h+0jW@ezYU#s2B9Xd7BfrmNZhO90r8}|a={0|C!hwX|DH9;$nM8)fU)*c~I zpB;B-x`Z8)VqGdS-$o$Z3lqaJZuR2k^tFW9THhze^RYd_%X#%=){@P;x}ATkVj{YdVComeXNr}?@;~l zhbFGDSMTa*KAvDYnKj{z+T=I7G<`vsZe|F*#2i}4xvyG}R~xw}l&)FCRR>@8o5>A+ z;8J&%*<5+;Dm9T-RDQi-gYSmbXxNV(riyI55}Sd>;P!l=b3Z+&x}xv%-X@n{KJ_w(Gj76brN%n2M(W;m zQoWTe;~t#r3T5N+)S{T%CcS^%uHK61o=TL`=^+16)K=B*fPc{OOEUR#{|W3bl)&DV zHBQ;P3!zGS9@hjJofnRVCcfo3>D|;}y0{x*U1AR5X(L{9I-`*ehqZd_`f2 zODm_eT4lX0yxVuM)o1_1x7F5&h7RRcdq8v_TWbApv9r#SGdiXoYuUbu0{5pSt(p*&fui@oCTT&~Xe)!b7%=Fn1pf=RAp?B9GPTQ^oCR2(o@IsW7!OYJy7 zLE)N_!o=rI)tKVpU~Suqh56UsAK$YSEBoA0gc-lRT03P+u0L&A5fM4Ha|tZ+Gkvmp zb`r>?l5ZStk~P%ip+-YH(qV~3H~BWX38x@;npIxa9?bc}(q*KqxPyfnj8~6dL`TyX5$ zeB^Gl&fyF0kN0=l9g8=%#*)rHYD1k8H{#Q`uq^^u4&CyTgxLCL__-_Yzu34MKPf@{ zgO?r(f3cC2j0NyN1p1#y`IkWdEm9Hz(!cJ1@#z0;{m ../../../target/kibana-fleet/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-fleet/cypress/results/output.json --reportDir ../../../target/kibana-fleet/cypress/results && mkdir -p ../../../target/junit && cp ../../../target/kibana-fleet/cypress/results/*.xml ../../../target/junit/" } } diff --git a/x-pack/plugins/fleet/tsconfig.json b/x-pack/plugins/fleet/tsconfig.json index d0361f4550576c..7cc16fe6542680 100644 --- a/x-pack/plugins/fleet/tsconfig.json +++ b/x-pack/plugins/fleet/tsconfig.json @@ -6,8 +6,9 @@ "declaration": true, "declarationMap": true, }, + "exclude": ["cypress.config.ts"], "include": [ - // add all the folders containg files to be compiled + // add all the folders containing files to be compiled ".storybook/**/*", "common/**/*", "public/**/*", @@ -15,6 +16,7 @@ "server/**/*.json", "scripts/**/*", "package.json", + "cypress.config.ts", "../../../typings/**/*" ], "references": [ diff --git a/x-pack/plugins/osquery/cypress.config.ts b/x-pack/plugins/osquery/cypress.config.ts new file mode 100644 index 00000000000000..862b4a916beada --- /dev/null +++ b/x-pack/plugins/osquery/cypress.config.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'cypress'; + +// eslint-disable-next-line import/no-default-export +export default defineConfig({ + defaultCommandTimeout: 60000, + execTimeout: 120000, + pageLoadTimeout: 12000, + + retries: { + runMode: 1, + openMode: 0, + }, + + screenshotsFolder: '../../../target/kibana-osquery/cypress/screenshots', + trashAssetsBeforeRuns: false, + video: false, + videosFolder: '../../../target/kibana-osquery/cypress/videos', + viewportHeight: 900, + viewportWidth: 1440, + experimentalStudio: true, + + env: { + 'cypress-react-selector': { + root: '#osquery-app', + }, + }, + + e2e: { + baseUrl: 'http://localhost:5601', + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/x-pack/plugins/osquery/cypress/cypress.json b/x-pack/plugins/osquery/cypress/cypress.json deleted file mode 100644 index 5df26a922d7c3b..00000000000000 --- a/x-pack/plugins/osquery/cypress/cypress.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "baseUrl": "http://localhost:5620", - "defaultCommandTimeout": 60000, - "execTimeout": 120000, - "pageLoadTimeout": 12000, - "retries": { - "runMode": 1, - "openMode": 0 - }, - "screenshotsFolder": "../../../target/kibana-osquery/cypress/screenshots", - "trashAssetsBeforeRuns": false, - "video": false, - "videosFolder": "../../../target/kibana-osquery/cypress/videos", - "viewportHeight": 900, - "viewportWidth": 1440, - "experimentalStudio": true, - "env": { - "cypress-react-selector": { - "root": "#osquery-app" - } - } -} diff --git a/x-pack/plugins/osquery/cypress/integration/all/add_integration.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/add_integration.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/all/alerts.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/alerts.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/all/discover.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/discover.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/discover.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/discover.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/all/edit_saved_queries.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/edit_saved_queries.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/edit_saved_queries.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/edit_saved_queries.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/all/live_query.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/live_query.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/all/metrics.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/metrics.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/all/packs.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/packs.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/all/saved_queries.spec.ts b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/all/saved_queries.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/roles/admin.spec.ts b/x-pack/plugins/osquery/cypress/e2e/roles/admin.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/roles/admin.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/roles/admin.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/roles/alert_test.spec.ts b/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/roles/alert_test.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/roles/reader.spec.ts b/x-pack/plugins/osquery/cypress/e2e/roles/reader.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/roles/reader.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/roles/reader.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/roles/t1_analyst.spec.ts b/x-pack/plugins/osquery/cypress/e2e/roles/t1_analyst.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/roles/t1_analyst.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/roles/t1_analyst.cy.ts diff --git a/x-pack/plugins/osquery/cypress/integration/roles/t2_analyst.spec.ts b/x-pack/plugins/osquery/cypress/e2e/roles/t2_analyst.cy.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/integration/roles/t2_analyst.spec.ts rename to x-pack/plugins/osquery/cypress/e2e/roles/t2_analyst.cy.ts diff --git a/x-pack/plugins/osquery/cypress/support/coverage.ts b/x-pack/plugins/osquery/cypress/support/coverage.ts index 65975f65af24fe..9278edfcc6ddd7 100644 --- a/x-pack/plugins/osquery/cypress/support/coverage.ts +++ b/x-pack/plugins/osquery/cypress/support/coverage.ts @@ -47,7 +47,8 @@ const logMessage = (s: string) => { * If there are more files loaded from support folder, also removes them */ const filterSupportFilesFromCoverage = (totalCoverage: any) => { - const integrationFolder = Cypress.config('integrationFolder'); + // @ts-expect-error update types + const integrationFolder = Cypress.config('e2eFolder'); const supportFile = Cypress.config('supportFile'); /** @type {string} Cypress run-time config has the support folder string */ @@ -64,6 +65,7 @@ const filterSupportFilesFromCoverage = (totalCoverage: any) => { // if we have files from support folder AND the support folder is not same // as the integration, or its prefix (this might remove all app source files) // then remove all files from the support folder + // @ts-expect-error update types if (!integrationFolder.startsWith(supportFolder)) { // remove all covered files from support folder coverage = Cypress._.omitBy(totalCoverage, (fileCoverage, filename) => diff --git a/x-pack/plugins/osquery/cypress/support/index.ts b/x-pack/plugins/osquery/cypress/support/e2e.ts similarity index 100% rename from x-pack/plugins/osquery/cypress/support/index.ts rename to x-pack/plugins/osquery/cypress/support/e2e.ts diff --git a/x-pack/plugins/osquery/cypress/tsconfig.json b/x-pack/plugins/osquery/cypress/tsconfig.json index cbb5b10c48aaf2..548ac5dc3eb130 100644 --- a/x-pack/plugins/osquery/cypress/tsconfig.json +++ b/x-pack/plugins/osquery/cypress/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../../../../tsconfig.base.json", "include": [ - "**/*" + "**/*", + "../cypress.config.ts" ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/osquery/package.json b/x-pack/plugins/osquery/package.json index 8d0e928f727707..fdda0a2316779b 100644 --- a/x-pack/plugins/osquery/package.json +++ b/x-pack/plugins/osquery/package.json @@ -5,9 +5,9 @@ "private": true, "license": "Elastic-License", "scripts": { - "cypress:open": "../../../node_modules/.bin/cypress open --config-file ./cypress/cypress.json", + "cypress:open": "../../../node_modules/.bin/cypress open --config-file ./cypress.config.ts", "cypress:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/osquery_cypress/visual_config.ts", - "cypress:run": "../../../node_modules/.bin/cypress run --config-file ./cypress/cypress.json", + "cypress:run": "../../../node_modules/.bin/cypress run --config-file ./cypress.config.ts", "cypress:run-as-ci": "node ../../../scripts/functional_tests --config ../../test/osquery_cypress/cli_config.ts", "nyc": "../../../node_modules/.bin/nyc report --reporter=text-summary" } diff --git a/x-pack/plugins/osquery/tsconfig.json b/x-pack/plugins/osquery/tsconfig.json index 4eac1baa43d791..f9cacf100b6918 100644 --- a/x-pack/plugins/osquery/tsconfig.json +++ b/x-pack/plugins/osquery/tsconfig.json @@ -6,6 +6,7 @@ "declaration": true, "declarationMap": true }, + "exclude": ["cypress.config.ts"], "include": [ // add all the folders contains files to be compiled "common/**/*", @@ -13,6 +14,7 @@ "scripts/**/*", "scripts/**/**.json", "server/**/*", + "cypress.config.ts", "../../../typings/**/*", // ECS and Osquery schema files "public/common/schemas/*/**.json", diff --git a/x-pack/plugins/security_solution/cypress/README.md b/x-pack/plugins/security_solution/cypress/README.md index 44f1fa63d732b1..5124e8d5c06858 100644 --- a/x-pack/plugins/security_solution/cypress/README.md +++ b/x-pack/plugins/security_solution/cypress/README.md @@ -83,7 +83,7 @@ This configuration runs cypress tests against an arbitrary host. #### integration-test (CI) -This configuration is driven by [elastic/integration-test](https://github.com/elastic/integration-test) which, as part of a bigger set of tests, provisions one VM with two instances configured in CCS mode and runs the [CCS Cypress test specs](./ccs_integration). +This configuration is driven by [elastic/integration-test](https://github.com/elastic/integration-test) which, as part of a bigger set of tests, provisions one VM with two instances configured in CCS mode and runs the [CCS Cypress test specs](./ccs_e2e). The two clusters are named `admin` and `data` and are reachable as follows: @@ -280,13 +280,13 @@ If you are debugging a flaky test, a good tip is to insert a `cy.wait( { deleteRuleFromDetailsPage(); + // @ts-expect-error update types cy.waitFor('@deleteRule').then(() => { cy.get(RULES_TABLE).should('exist'); cy.get(RULES_TABLE) diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule_data_view.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule_data_view.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule_data_view.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/custom_query_rule_data_view.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/event_correlation_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/event_correlation_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/export_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/export_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/import_rules.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/import_rules.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/import_rules.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/import_rules.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/indicator_match_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/links.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/links.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/links.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/links.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/machine_learning_rule.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/machine_learning_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/machine_learning_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/machine_learning_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/new_terms_rule.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/new_terms_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/new_terms_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/new_terms_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/override.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/override.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/prebuilt_rules.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/prebuilt_rules.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/prebuilt_rules.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/related_integrations.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/related_integrations.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/rules_selection.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_selection.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/rules_selection.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_selection.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/rules_table_auto_refresh.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_table_auto_refresh.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/rules_table_auto_refresh.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/rules_table_auto_refresh.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/sorting.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/sorting.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/threshold_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/detection_rules/threshold_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/alerts_table_flow/add_exception.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/alerts_table_flow/add_exception.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/alerts_table_flow/add_exception.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/alerts_table_flow/add_exception.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_flyout.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_flyout.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_flyout.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_management_flow/all_exception_lists_read_only.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/all_exception_lists_read_only.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_management_flow/all_exception_lists_read_only.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/all_exception_lists_read_only.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_table.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_table.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_exception.spec.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_exception.spec.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception_data_view.spect.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_exception_data_view.spect.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/add_exception_data_view.spect.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/add_exception_data_view.spect.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/edit_exception.spec.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/edit_exception.spec.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception_data_view.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/edit_exception_data_view.spec.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/edit_exception_data_view.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/edit_exception_data_view.spec.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/read_only_view.spect.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/read_only_view.spect.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/exceptions/rule_details_flow/read_only_view.spect.ts rename to x-pack/plugins/security_solution/cypress/e2e/exceptions/rule_details_flow/read_only_view.spect.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/filters/pinned_filters.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/filters/pinned_filters.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/filters/pinned_filters.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/filters/pinned_filters.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/guided_onboarding/tour.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/guided_onboarding/tour.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/guided_onboarding/tour.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/guided_onboarding/tour.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/header/navigation.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/header/navigation.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/header/navigation.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/header/navigation.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/header/search_bar.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/header/search_bar.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/header/search_bar.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/header/search_bar.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/host_details/risk_tab.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/host_details/risk_tab.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/host_details/risk_tab.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/host_details/risk_tab.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/hosts/events_viewer.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/hosts/events_viewer.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/hosts/events_viewer.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/hosts/events_viewer.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/hosts/host_risk_tab.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/hosts/host_risk_tab.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/hosts/host_risk_tab.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/hosts/host_risk_tab.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/hosts/hosts_risk_column.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/hosts/hosts_risk_column.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/hosts/hosts_risk_column.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/hosts/hosts_risk_column.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/hosts/inspect.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/hosts/inspect.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/hosts/inspect.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/hosts/inspect.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/ml/ml_conditional_links.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/ml/ml_conditional_links.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/network/hover_actions.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/network/hover_actions.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/network/hover_actions.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/network/hover_actions.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/network/inspect.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/network/inspect.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/network/inspect.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/network/inspect.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/network/overflow_items.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/network/overflow_items.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/network/overflow_items.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/network/overflow_items.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/overview/cti_link_panel.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/overview/cti_link_panel.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/overview/cti_link_panel.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/overview/cti_link_panel.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/overview/overview.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/overview/overview.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/overview/overview.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/overview/overview.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/pagination/pagination.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/pagination/pagination.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/pagination/pagination.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/pagination/pagination.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timeline_templates/creation.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timeline_templates/creation.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timeline_templates/export.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timeline_templates/export.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/creation.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/creation.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/data_providers.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/data_providers.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/data_providers.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/data_providers.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/export.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/export.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/fields_browser.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/fields_browser.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/fields_browser.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/fields_browser.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/flyout_button.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/flyout_button.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/flyout_button.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/flyout_button.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/full_screen.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/full_screen.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/full_screen.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/full_screen.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/inspect.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/inspect.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/inspect.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/inspect.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/local_storage.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/local_storage.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/local_storage.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/local_storage.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/notes_tab.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/notes_tab.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/notes_tab.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/notes_tab.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/open_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/open_timeline.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/open_timeline.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/open_timeline.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/overview.tsx b/x-pack/plugins/security_solution/cypress/e2e/timelines/overview.cy.tsx similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/overview.tsx rename to x-pack/plugins/security_solution/cypress/e2e/timelines/overview.cy.tsx diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/pagination.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/pagination.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/pagination.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/pagination.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/query_tab.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/query_tab.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/query_tab.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/query_tab.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/row_renderers.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/row_renderers.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/row_renderers.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/row_renderers.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/search_or_filter.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/search_or_filter.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/search_or_filter.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/search_or_filter.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/toggle_column.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/timelines/toggle_column.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/timelines/toggle_column.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/timelines/toggle_column.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/urls/compatibility.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/urls/compatibility.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/urls/compatibility.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/urls/compatibility.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/urls/not_found.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/urls/not_found.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/urls/not_found.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/urls/not_found.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/urls/state.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/urls/state.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/users/inspect.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/users/inspect.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/users/inspect.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/users/inspect.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/users/user_details.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/users/user_details.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/users/user_details.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/users/user_details.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/users/users_tabs.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/users/users_tabs.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/users/users_tabs.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/users/users_tabs.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/value_lists/value_lists.spec.ts b/x-pack/plugins/security_solution/cypress/e2e/value_lists/value_lists.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/integration/value_lists/value_lists.spec.ts rename to x-pack/plugins/security_solution/cypress/e2e/value_lists/value_lists.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/support/index.js b/x-pack/plugins/security_solution/cypress/support/e2e.js similarity index 100% rename from x-pack/plugins/security_solution/cypress/support/index.js rename to x-pack/plugins/security_solution/cypress/support/e2e.js diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/detections/detection_rules/custom_query_rule.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_e2e/detections/detection_rules/custom_query_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/upgrade_integration/detections/detection_rules/custom_query_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/upgrade_e2e/detections/detection_rules/custom_query_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/detections/detection_rules/threshold_rule.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_e2e/detections/detection_rules/threshold_rule.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/upgrade_integration/detections/detection_rules/threshold_rule.spec.ts rename to x-pack/plugins/security_solution/cypress/upgrade_e2e/detections/detection_rules/threshold_rule.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/cases/import_case.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_e2e/threat_hunting/cases/import_case.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/cases/import_case.spec.ts rename to x-pack/plugins/security_solution/cypress/upgrade_e2e/threat_hunting/cases/import_case.cy.ts diff --git a/x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/timeline/import_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/upgrade_e2e/threat_hunting/timeline/import_timeline.cy.ts similarity index 100% rename from x-pack/plugins/security_solution/cypress/upgrade_integration/threat_hunting/timeline/import_timeline.spec.ts rename to x-pack/plugins/security_solution/cypress/upgrade_e2e/threat_hunting/timeline/import_timeline.cy.ts diff --git a/x-pack/plugins/security_solution/package.json b/x-pack/plugins/security_solution/package.json index 92a934f2dd674d..987bcdbe271938 100644 --- a/x-pack/plugins/security_solution/package.json +++ b/x-pack/plugins/security_solution/package.json @@ -8,21 +8,20 @@ "extract-mitre-attacks": "node scripts/extract_tactics_techniques_mitre.js && node ../../../scripts/eslint ./public/detections/mitre/mitre_tactics_techniques.ts --fix", "build-beat-doc": "node scripts/beat_docs/build.js && node ../../../scripts/eslint ../timelines/server/utils/beat_schema/fields.ts --fix", "cypress": "../../../node_modules/.bin/cypress", - "cypress:open": "yarn cypress open --config-file ./cypress/cypress.json", - "cypress:open:ccs": "yarn cypress:open --config integrationFolder=./cypress/ccs_integration", + "cypress:open": "yarn cypress open --config-file ./cypress/cypress.config.ts", + "cypress:open:ccs": "yarn cypress:open --config specPattern=./cypress/ccs_e2e/**/*.cy.ts", "cypress:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/security_solution_cypress/visual_config.ts", - "cypress:open:upgrade": "yarn cypress:open --config integrationFolder=./cypress/upgrade_integration", - "cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/integration/**/*.spec.ts'; status=$?; yarn junit:merge && exit $status", - "cypress:run:spec": "yarn cypress:run:reporter --browser chrome --spec ${SPEC_LIST:-'./cypress/integration/**/*.spec.ts'}; status=$?; yarn junit:merge && exit $status", - "cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/integration/cases/*.spec.ts'; status=$?; yarn junit:merge && exit $status", - "cypress:run:firefox": "yarn cypress:run:reporter --browser firefox --spec './cypress/integration/**/*.spec.ts'; status=$?; yarn junit:merge && exit $status", - "cypress:run:reporter": "yarn cypress run --config-file ./cypress/cypress_ci.json --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json", - "cypress:run:respops": "yarn cypress:run:reporter --browser chrome --spec ./cypress/integration/detection_alerts/*.spec.ts,./cypress/integration/detection_rules/*.spec.ts,./cypress/integration/exceptions/*.spec.ts; status=$?; yarn junit:merge && exit $status", - "cypress:run:ccs": "yarn cypress:run:reporter --browser chrome --config integrationFolder=./cypress/ccs_integration; status=$?; yarn junit:merge && exit $status", + "cypress:open:upgrade": "yarn cypress:open --config specPattern=./cypress/upgrade_e2e/**/*.cy.ts", + "cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status", + "cypress:run:spec": "yarn cypress:run:reporter --browser chrome --spec ${SPEC_LIST:-'./cypress/e2e/**/*.cy.ts'}; status=$?; yarn junit:merge && exit $status", + "cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/cases/*.cy.ts'; status=$?; yarn junit:merge && exit $status", + "cypress:run:firefox": "yarn cypress:run:reporter --browser firefox --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status", + "cypress:run:reporter": "yarn cypress run --config-file ./cypress/cypress_ci.config.ts --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json", + "cypress:run:respops": "yarn cypress:run:reporter --browser chrome --spec ./cypress/e2e/detection_alerts/*.cy.ts,./cypress/e2e/detection_rules/*.cy.ts,./cypress/e2e/exceptions/*.cy.ts; status=$?; yarn junit:merge && exit $status", + "cypress:run:ccs": "yarn cypress:run:reporter --browser chrome --config specPattern=./cypress/ccs_e2e/**/*.cy.ts; status=$?; yarn junit:merge && exit $status", "cypress:run-as-ci": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/security_solution_cypress/cli_config_parallel.ts", "cypress:run-as-ci:firefox": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/security_solution_cypress/config.firefox.ts", - "cypress:run:upgrade": "yarn cypress:run:reporter --browser chrome --config integrationFolder=./cypress/upgrade_integration", - "cypress:run:upgrade:old": "yarn cypress:run:reporter --browser chrome --config integrationFolder=./cypress/upgrade_integration --spec ./cypress/upgrade_integration/threat_hunting/**/*.spec.ts,./cypress/upgrade_integration/detections/**/custom_query_rule.spec.ts; status=$?; yarn junit:merge && exit $status", + "cypress:run:upgrade": "yarn cypress:run:reporter --browser chrome --config specPattern=./cypress/upgrade_e2e/**/*.cy.ts", "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results && mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/", "test:generate": "node scripts/endpoint/resolver_generator" } diff --git a/x-pack/plugins/threat_intelligence/cypress/cypress.config.ts b/x-pack/plugins/threat_intelligence/cypress/cypress.config.ts new file mode 100644 index 00000000000000..540485920c2ffe --- /dev/null +++ b/x-pack/plugins/threat_intelligence/cypress/cypress.config.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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import { defineConfig } from 'cypress'; + +// eslint-disable-next-line import/no-default-export +export default defineConfig({ + defaultCommandTimeout: 120000, + execTimeout: 120000, + pageLoadTimeout: 120000, + retries: { + runMode: 2, + }, + screenshotsFolder: '../../../target/kibana-threat-intelligence/cypress/screenshots', + trashAssetsBeforeRuns: false, + video: false, + videosFolder: '../../../target/kibana-threat-intelligence/cypress/videos', + viewportHeight: 946, + viewportWidth: 1680, + env: { + protocol: 'http', + hostname: 'localhost', + configport: '5601', + }, + e2e: { + baseUrl: 'http://localhost:5601', + setupNodeEvents(on, config) { + // eslint-disable-next-line @typescript-eslint/no-var-requires + return require('./plugins')(on, config); + }, + }, +}); diff --git a/x-pack/plugins/threat_intelligence/cypress/cypress.json b/x-pack/plugins/threat_intelligence/cypress/cypress.json deleted file mode 100644 index 90b6cdb52e3c17..00000000000000 --- a/x-pack/plugins/threat_intelligence/cypress/cypress.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "baseUrl": "http://localhost:5601", - "defaultCommandTimeout": 120000, - "execTimeout": 120000, - "pageLoadTimeout": 120000, - "retries": { - "runMode": 2 - }, - "screenshotsFolder": "../../../target/kibana-threat-intelligence/cypress/screenshots", - "trashAssetsBeforeRuns": false, - "video": false, - "videosFolder": "../../../target/kibana-threat-intelligence/cypress/videos", - "viewportHeight": 946, - "viewportWidth": 1680, - "env": { - "protocol": "http", - "hostname": "localhost", - "configport": "5601" - } -} diff --git a/x-pack/plugins/threat_intelligence/cypress/integration/empty_page.spec.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/empty_page.cy.ts similarity index 100% rename from x-pack/plugins/threat_intelligence/cypress/integration/empty_page.spec.ts rename to x-pack/plugins/threat_intelligence/cypress/e2e/empty_page.cy.ts diff --git a/x-pack/plugins/threat_intelligence/cypress/integration/indicators.spec.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts similarity index 100% rename from x-pack/plugins/threat_intelligence/cypress/integration/indicators.spec.ts rename to x-pack/plugins/threat_intelligence/cypress/e2e/indicators.cy.ts diff --git a/x-pack/plugins/threat_intelligence/cypress/integration/query_bar.spec.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/query_bar.cy.ts similarity index 100% rename from x-pack/plugins/threat_intelligence/cypress/integration/query_bar.spec.ts rename to x-pack/plugins/threat_intelligence/cypress/e2e/query_bar.cy.ts diff --git a/x-pack/plugins/threat_intelligence/cypress/integration/timeline.spec.ts b/x-pack/plugins/threat_intelligence/cypress/e2e/timeline.cy.ts similarity index 100% rename from x-pack/plugins/threat_intelligence/cypress/integration/timeline.spec.ts rename to x-pack/plugins/threat_intelligence/cypress/e2e/timeline.cy.ts diff --git a/x-pack/plugins/threat_intelligence/cypress/support/index.js b/x-pack/plugins/threat_intelligence/cypress/support/e2e.js similarity index 100% rename from x-pack/plugins/threat_intelligence/cypress/support/index.js rename to x-pack/plugins/threat_intelligence/cypress/support/e2e.js diff --git a/x-pack/plugins/threat_intelligence/package.json b/x-pack/plugins/threat_intelligence/package.json index 1af856fcdf6164..ebbe810a6629c3 100644 --- a/x-pack/plugins/threat_intelligence/package.json +++ b/x-pack/plugins/threat_intelligence/package.json @@ -3,21 +3,16 @@ "name": "threat_intelligence", "scripts": { "cypress": "../../../node_modules/.bin/cypress", - "cypress:open": "yarn cypress open --config-file ./cypress/cypress.json", - "cypress:open:ccs": "yarn cypress:open --config integrationFolder=./cypress/ccs_integration", + "cypress:open": "yarn cypress open --config-file ./cypress/cypress.config.ts", "cypress:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/threat_intelligence_cypress/visual_config.ts", - "cypress:open:upgrade": "yarn cypress:open --config integrationFolder=./cypress/upgrade_integration", - "cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/integration/**/*.spec.ts'; status=$?; yarn junit:merge && exit $status", - "cypress:run:spec": "yarn cypress:run:reporter --browser chrome --spec ${SPEC_LIST:-'./cypress/integration/**/*.spec.ts'}; status=$?; yarn junit:merge && exit $status", - "cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/integration/cases/*.spec.ts'; status=$?; yarn junit:merge && exit $status", - "cypress:run:firefox": "yarn cypress:run:reporter --browser firefox --spec './cypress/integration/**/*.spec.ts'; status=$?; yarn junit:merge && exit $status", - "cypress:run:reporter": "yarn cypress run --config-file ./cypress/cypress.json --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json", - "cypress:run:respops": "yarn cypress:run:reporter --browser chrome --spec ./cypress/integration/detection_alerts/*.spec.ts,./cypress/integration/detection_rules/*.spec.ts,./cypress/integration/exceptions/*.spec.ts; status=$?; yarn junit:merge && exit $status", - "cypress:run:ccs": "yarn cypress:run:reporter --browser chrome --config integrationFolder=./cypress/ccs_integration; status=$?; yarn junit:merge && exit $status", + "cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status", + "cypress:run:spec": "yarn cypress:run:reporter --browser chrome --spec ${SPEC_LIST:-'./cypress/e2e/**/*.cy.ts'}; status=$?; yarn junit:merge && exit $status", + "cypress:run:cases": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/cases/*.cy.ts'; status=$?; yarn junit:merge && exit $status", + "cypress:run:firefox": "yarn cypress:run:reporter --browser firefox --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status", + "cypress:run:reporter": "yarn cypress run --config-file ./cypress/cypress.config.ts --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json", + "cypress:run:respops": "yarn cypress:run:reporter --browser chrome --spec ./cypress/e2e/detection_alerts/*.cy.ts,./cypress/e2e/detection_rules/*.cy.ts,./cypress/e2e/exceptions/*.cy.ts; status=$?; yarn junit:merge && exit $status", "cypress:run-as-ci": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/threat_intelligence_cypress/cli_config_parallel.ts", "cypress:run-as-ci:firefox": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/threat_intelligence_cypress/config.firefox.ts", - "cypress:run:upgrade": "yarn cypress:run:reporter --browser chrome --config integrationFolder=./cypress/upgrade_integration", - "cypress:run:upgrade:old": "yarn cypress:run:reporter --browser chrome --config integrationFolder=./cypress/upgrade_integration --spec ./cypress/upgrade_integration/threat_hunting/**/*.spec.ts,./cypress/upgrade_integration/detections/**/custom_query_rule.spec.ts; status=$?; yarn junit:merge && exit $status", "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-threat-intelligence/cypress/results/mochawesome*.json > ../../../target/kibana-threat-intelligence/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-threat-intelligence/cypress/results/output.json --reportDir ../../../target/kibana-threat-intelligence/cypress/results && mkdir -p ../../../target/junit && cp ../../../target/kibana-threat-intelligence/cypress/results/*.xml ../../../target/junit/" } } diff --git a/x-pack/test/security_solution_cypress/runner.ts b/x-pack/test/security_solution_cypress/runner.ts index 79e202046a4e06..08dc0f949e01c6 100644 --- a/x-pack/test/security_solution_cypress/runner.ts +++ b/x-pack/test/security_solution_cypress/runner.ts @@ -17,10 +17,7 @@ import semver from 'semver'; import { FtrProviderContext } from './ftr_provider_context'; const retrieveIntegrations = (chunksTotal: number, chunkIndex: number) => { - const pattern = resolve( - __dirname, - '../../plugins/security_solution/cypress/integration/**/*.spec.ts' - ); + const pattern = resolve(__dirname, '../../plugins/security_solution/cypress/e2e/**/*.cy.ts'); const integrationsPaths = globby.sync(pattern); const chunkSize = Math.ceil(integrationsPaths.length / chunksTotal); diff --git a/x-pack/test/threat_intelligence_cypress/runner.ts b/x-pack/test/threat_intelligence_cypress/runner.ts index c165cb552b9bac..5ab9d032c55f29 100644 --- a/x-pack/test/threat_intelligence_cypress/runner.ts +++ b/x-pack/test/threat_intelligence_cypress/runner.ts @@ -22,10 +22,7 @@ import { tiAbusechMalwareBazaar } from './pipelines/ti_abusech_malware_bazaar'; import { tiAbusechUrl } from './pipelines/ti_abusech_url'; const retrieveIntegrations = (chunksTotal: number, chunkIndex: number) => { - const pattern = resolve( - __dirname, - '../../plugins/threat_intelligence/cypress/integration/**/*.spec.ts' - ); + const pattern = resolve(__dirname, '../../plugins/threat_intelligence/cypress/e2e/**/*.cy.ts'); const integrationsPaths = globby.sync(pattern); const chunkSize = Math.ceil(integrationsPaths.length / chunksTotal); diff --git a/yarn.lock b/yarn.lock index 1a56456289f138..ca0826165cf2ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -108,7 +108,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.19.0", "@babel/core@^7.7.5": +"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.19.0", "@babel/core@^7.7.5": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.0.tgz#d2f5f4f2033c00de8096be3c9f45772563e150c3" integrity sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ== @@ -414,7 +414,7 @@ "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.16.0", "@babel/plugin-proposal-class-properties@^7.18.6": +"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== @@ -505,7 +505,7 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.16.0", "@babel/plugin-proposal-object-rest-spread@^7.18.9": +"@babel/plugin-proposal-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7" integrity sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q== @@ -963,7 +963,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-runtime@^7.16.0", "@babel/plugin-transform-runtime@^7.18.10": +"@babel/plugin-transform-runtime@^7.18.10": version "7.18.10" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz#37d14d1fa810a368fd635d4d1476c0154144a96f" integrity sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ== @@ -1035,7 +1035,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.16.0", "@babel/preset-env@^7.19.0": +"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.0.tgz#fd18caf499a67d6411b9ded68dc70d01ed1e5da7" integrity sha512-1YUju1TAFuzjIQqNM9WsF4U6VbD/8t3wEAlw3LFYuuEr+ywqLRcSXxFKz4DCEj+sN94l/XTDiUXYRrsvMpz9WQ== @@ -1135,7 +1135,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.12.10", "@babel/preset-react@^7.16.0", "@babel/preset-react@^7.18.6": +"@babel/preset-react@^7.12.10", "@babel/preset-react@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== @@ -1175,7 +1175,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.0", "@babel/runtime@^7.19.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.0", "@babel/runtime@^7.15.4", "@babel/runtime@^7.19.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== @@ -1309,39 +1309,15 @@ resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz#b6b8d81780b9a9f6459f4bfe9226ac6aefaefe87" integrity sha512-aG20vknL4/YjQF9BSV7ts4EWm/yrjagAN7OWBNmlbEOUiu0llj4OGrFoOKK3g2vey4/p2omKCoHrWtPxSwV3HA== -"@cypress/browserify-preprocessor@3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@cypress/browserify-preprocessor/-/browserify-preprocessor-3.0.2.tgz#1dbecae394937aed47a3524cad47086c2ded8c50" - integrity sha512-y6mlFR+IR2cqcm3HabSp7AEcX9QfF1EUL4eOaw/7xexdhmdQU8ez6piyRopZQob4BK8oKTsc9PkupsU2rzjqMA== - dependencies: - "@babel/core" "^7.16.0" - "@babel/plugin-proposal-class-properties" "^7.16.0" - "@babel/plugin-proposal-object-rest-spread" "^7.16.0" - "@babel/plugin-transform-runtime" "^7.16.0" - "@babel/preset-env" "^7.16.0" - "@babel/preset-react" "^7.16.0" - "@babel/runtime" "^7.16.0" - babel-plugin-add-module-exports "^1.0.4" - babelify "^10.0.0" - bluebird "^3.7.2" - browserify "^16.2.3" - coffeeify "^3.0.1" - coffeescript "^1.12.7" - debug "^4.3.2" - fs-extra "^9.0.0" - lodash.clonedeep "^4.5.0" - through2 "^2.0.0" - watchify "^4.0.0" - -"@cypress/code-coverage@^3.9.12": - version "3.9.12" - resolved "https://registry.yarnpkg.com/@cypress/code-coverage/-/code-coverage-3.9.12.tgz#f1eab362a71734f997dfb870342cecff20dae23d" - integrity sha512-2QuDSQ2ovz2ZsbQImM917q+9JmEq4afC4kpgHe2o3rTQxUrs7CdHM84rT8XKl0gJIXmbMcNq2rZqe40/eFmCFw== +"@cypress/code-coverage@^3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@cypress/code-coverage/-/code-coverage-3.10.0.tgz#2132dbb7ae068cab91790926d50a9bf85140cab4" + integrity sha512-K5pW2KPpK4vKMXqxd6vuzo6m9BNgpAv1LcrrtmqAtOJ1RGoEILXYZVost0L6Q+V01NyY7n7jXIIfS7LR3nP6YA== dependencies: - "@cypress/browserify-preprocessor" "3.0.2" + "@cypress/webpack-preprocessor" "^5.11.0" chalk "4.1.2" dayjs "1.10.7" - debug "4.3.3" + debug "4.3.4" execa "4.1.0" globby "11.0.4" istanbul-lib-coverage "3.0.0" @@ -1386,13 +1362,13 @@ snap-shot-compare "2.8.3" snap-shot-store "1.2.3" -"@cypress/webpack-preprocessor@^5.6.0": - version "5.6.0" - resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-5.6.0.tgz#9648ae22d2e52f17a604e2a493af27a9c96568bd" - integrity sha512-kSelTDe6gs3Skp4vPP2vfTvAl+Ua+9rR/AMTir7bgJihDvzFESqnjWtF6N1TrPo+vCFVGx0VUA6JUvDkhvpwhA== +"@cypress/webpack-preprocessor@^5.11.0", "@cypress/webpack-preprocessor@^5.12.2": + version "5.12.2" + resolved "https://registry.yarnpkg.com/@cypress/webpack-preprocessor/-/webpack-preprocessor-5.12.2.tgz#9cc623a5629980d7f2619569bffc8e3f05a701ae" + integrity sha512-t29wEFvI87IMnCd8taRunwStNsFjFWg138fGF0hPQOYgSj30fbzCEwFD9cAQLYMMcjjuXcnnw8yOfkzIZBBNVQ== dependencies: - bluebird "^3.7.1" - debug "4.3.2" + bluebird "3.7.1" + debug "^4.3.2" lodash "^4.17.20" "@cypress/xvfb@^1.2.4": @@ -5982,14 +5958,7 @@ "@types/babel__template" "*" "@types/babel__traverse" "*" -"@types/babel__generator@*": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.0.2.tgz#d2112a6b21fad600d7674274293c85dce0cb47fc" - integrity sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__generator@^7.6.4": +"@types/babel__generator@*", "@types/babel__generator@^7.6.4": version "7.6.4" resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== @@ -9104,7 +9073,7 @@ resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== -JSONStream@1.3.5, JSONStream@^1.0.3: +JSONStream@1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== @@ -9150,7 +9119,7 @@ acorn-jsx@^5.3.1: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== -acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2, acorn-node@^1.6.1: +acorn-node@^1.3.0, acorn-node@^1.6.1: version "1.8.2" resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== @@ -9453,7 +9422,7 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -anymatch@^3.0.0, anymatch@^3.0.3, anymatch@^3.1.0, anymatch@~3.1.2: +anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== @@ -9781,7 +9750,7 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= -assert@^1.1.1, assert@^1.4.0: +assert@^1.1.1: version "1.5.0" resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== @@ -10216,11 +10185,6 @@ babel-runtime@6.x, babel-runtime@^6.26.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -babelify@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-10.0.0.tgz#fe73b1a22583f06680d8d072e25a1e0d1d1d7fb5" - integrity sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg== - backport@^8.9.2: version "8.9.2" resolved "https://registry.yarnpkg.com/backport/-/backport-8.9.2.tgz#cf0ec69428f9e86c20e1898dd77e8f6c12bf5afa" @@ -10375,7 +10339,12 @@ blob-util@^2.0.2: resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== -bluebird@3.7.2, bluebird@^3.3.5, bluebird@^3.5.5, bluebird@^3.7.1, bluebird@^3.7.2: +bluebird@3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" + integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== + +bluebird@3.7.2, bluebird@^3.3.5, bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -10505,18 +10474,6 @@ brotli@^1.2.0: dependencies: base64-js "^1.1.2" -browser-pack@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" - integrity sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA== - dependencies: - JSONStream "^1.0.3" - combine-source-map "~0.8.0" - defined "^1.0.0" - safe-buffer "^5.1.1" - through2 "^2.0.0" - umd "^3.0.0" - browser-process-hrtime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" @@ -10529,13 +10486,6 @@ browser-resolve@^1.8.1: dependencies: resolve "1.1.7" -browser-resolve@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-2.0.0.tgz#99b7304cb392f8d73dba741bb2d7da28c6d7842b" - integrity sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ== - dependencies: - resolve "^1.17.0" - browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" @@ -10601,121 +10551,13 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" -browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: +browserify-zlib@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" -browserify@^16.2.3: - version "16.5.2" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.5.2.tgz#d926835e9280fa5fd57f5bc301f2ef24a972ddfe" - integrity sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g== - dependencies: - JSONStream "^1.0.3" - assert "^1.4.0" - browser-pack "^6.0.1" - browser-resolve "^2.0.0" - browserify-zlib "~0.2.0" - buffer "~5.2.1" - cached-path-relative "^1.0.0" - concat-stream "^1.6.0" - console-browserify "^1.1.0" - constants-browserify "~1.0.0" - crypto-browserify "^3.0.0" - defined "^1.0.0" - deps-sort "^2.0.0" - domain-browser "^1.2.0" - duplexer2 "~0.1.2" - events "^2.0.0" - glob "^7.1.0" - has "^1.0.0" - htmlescape "^1.1.0" - https-browserify "^1.0.0" - inherits "~2.0.1" - insert-module-globals "^7.0.0" - labeled-stream-splicer "^2.0.0" - mkdirp-classic "^0.5.2" - module-deps "^6.2.3" - os-browserify "~0.3.0" - parents "^1.0.1" - path-browserify "~0.0.0" - process "~0.11.0" - punycode "^1.3.2" - querystring-es3 "~0.2.0" - read-only-stream "^2.0.0" - readable-stream "^2.0.2" - resolve "^1.1.4" - shasum "^1.0.0" - shell-quote "^1.6.1" - stream-browserify "^2.0.0" - stream-http "^3.0.0" - string_decoder "^1.1.1" - subarg "^1.0.0" - syntax-error "^1.1.1" - through2 "^2.0.0" - timers-browserify "^1.0.1" - tty-browserify "0.0.1" - url "~0.11.0" - util "~0.10.1" - vm-browserify "^1.0.0" - xtend "^4.0.0" - -browserify@^17.0.0: - version "17.0.0" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-17.0.0.tgz#4c48fed6c02bfa2b51fd3b670fddb805723cdc22" - integrity sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w== - dependencies: - JSONStream "^1.0.3" - assert "^1.4.0" - browser-pack "^6.0.1" - browser-resolve "^2.0.0" - browserify-zlib "~0.2.0" - buffer "~5.2.1" - cached-path-relative "^1.0.0" - concat-stream "^1.6.0" - console-browserify "^1.1.0" - constants-browserify "~1.0.0" - crypto-browserify "^3.0.0" - defined "^1.0.0" - deps-sort "^2.0.1" - domain-browser "^1.2.0" - duplexer2 "~0.1.2" - events "^3.0.0" - glob "^7.1.0" - has "^1.0.0" - htmlescape "^1.1.0" - https-browserify "^1.0.0" - inherits "~2.0.1" - insert-module-globals "^7.2.1" - labeled-stream-splicer "^2.0.0" - mkdirp-classic "^0.5.2" - module-deps "^6.2.3" - os-browserify "~0.3.0" - parents "^1.0.1" - path-browserify "^1.0.0" - process "~0.11.0" - punycode "^1.3.2" - querystring-es3 "~0.2.0" - read-only-stream "^2.0.0" - readable-stream "^2.0.2" - resolve "^1.1.4" - shasum-object "^1.0.0" - shell-quote "^1.6.1" - stream-browserify "^3.0.0" - stream-http "^3.0.0" - string_decoder "^1.1.1" - subarg "^1.0.0" - syntax-error "^1.1.1" - through2 "^2.0.0" - timers-browserify "^1.0.1" - tty-browserify "0.0.1" - url "~0.11.0" - util "~0.12.0" - vm-browserify "^1.0.0" - xtend "^4.0.0" - browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.16.6, browserslist@^4.20.2, browserslist@^4.20.3: version "4.21.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.0.tgz#7ab19572361a140ecd1e023e2c1ed95edda0cefe" @@ -10793,14 +10635,6 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@~5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - integrity sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -10912,11 +10746,6 @@ cacheable-request@^7.0.2: normalize-url "^6.0.1" responselike "^2.0.0" -cached-path-relative@^1.0.0, cached-path-relative@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.2.tgz#a13df4196d26776220cc3356eb147a52dba2c6db" - integrity sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg== - cachedir@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" @@ -11472,19 +11301,6 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -coffeeify@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/coffeeify/-/coffeeify-3.0.1.tgz#5e2753000c50bd24c693115f33864248dd11136c" - integrity sha512-Qjnr7UX6ldK1PHV7wCnv7AuCd4q19KTUtwJnu/6JRJB4rfm12zvcXtKdacUoePOKr1I4ka/ydKiwWpNAdsQb0g== - dependencies: - convert-source-map "^1.3.0" - through2 "^2.0.0" - -coffeescript@^1.12.7: - version "1.12.7" - resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-1.12.7.tgz#e57ee4c4867cf7f606bfc4a0f2d550c0981ddd27" - integrity sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA== - collapse-white-space@^1.0.2: version "1.0.6" resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" @@ -11584,16 +11400,6 @@ colorspace@1.1.x: color "3.0.x" text-hex "1.0.x" -combine-source-map@^0.8.0, combine-source-map@~0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" - integrity sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos= - dependencies: - convert-source-map "~1.1.0" - inline-source-map "~0.6.0" - lodash.memoize "~3.0.3" - source-map "~0.5.3" - combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz" @@ -11722,7 +11528,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@~1.6.0: +concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@~1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -11798,7 +11604,7 @@ console-log-level@^1.4.1: resolved "https://registry.yarnpkg.com/console-log-level/-/console-log-level-1.4.1.tgz#9c5a6bb9ef1ef65b05aba83028b0ff894cdf630a" integrity sha512-VZzbIORbP+PPcN/gg3DXClTLPLg5Slwd5fL2MIc+o1qZ4BXBvWyc6QxPk6T/Mkr6IVjRpoAGf32XxP3ZWMVRcQ== -constants-browserify@^1.0.0, constants-browserify@~1.0.0: +constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= @@ -11832,18 +11638,13 @@ contentstream@^1.0.0: dependencies: readable-stream "~1.0.33-1" -convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.3.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@1.X, convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" -convert-source-map@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" - integrity sha1-SCnId+n+SbMWHzvzZziI4gRpmGA= - cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -12082,7 +11883,7 @@ crypt@~0.0.1: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= -crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: +crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== @@ -12350,20 +12151,20 @@ cyclist@~0.2.2: resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= -cypress-axe@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/cypress-axe/-/cypress-axe-0.14.0.tgz#5f5e70fb36b8cb3ba73a8ba01e9262ff1268d5e2" - integrity sha512-7Rdjnko0MjggCmndc1wECAkvQBIhuy+DRtjF7bd5YPZRFvubfMNvrxfqD8PWQmxm7MZE0ffS4Xr43V6ZmvLopg== +cypress-axe@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cypress-axe/-/cypress-axe-1.0.0.tgz#ab4e9486eaa3bb956a90a1ae40d52df42827b4f0" + integrity sha512-QBlNMAd5eZoyhG8RGGR/pLtpHGkvgWXm2tkP68scJ+AjYiNNOlJihxoEwH93RT+rWOLrefw4iWwEx8kpEcrvJA== cypress-file-upload@^5.0.8: version "5.0.8" resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-5.0.8.tgz#d8824cbeaab798e44be8009769f9a6c9daa1b4a1" integrity sha512-+8VzNabRk3zG6x8f8BWArF/xA/W0VK4IZNx3MV0jFWrJS/qKn8eHfa5nU73P9fOQAgwHFJx7zjg4lwOnljMO8g== -cypress-multi-reporters@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.6.0.tgz#2c6833b92e3df412c233657c55009e2d5e1cc7c1" - integrity sha512-JN9yMzDmPwwirzi95N2FC8VJZ0qp+uUJ1ixYHpJFaAtGgIx15LjVmASqQaxnDh8q57jIIJ6C0o7imiLU6N1YNQ== +cypress-multi-reporters@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/cypress-multi-reporters/-/cypress-multi-reporters-1.6.1.tgz#515b891f6c80e0700068efb03ab9d55388399c95" + integrity sha512-FPeC0xWF1N6Myrwc2m7KC0xxlrtG8+x4hlsPFBDRWP8u/veR2x90pGaH3BuJfweV7xoQ4Zo85Qjhu3fgZGrBQQ== dependencies: debug "^4.1.1" lodash "^4.17.15" @@ -12373,27 +12174,27 @@ cypress-pipe@^2.0.0: resolved "https://registry.yarnpkg.com/cypress-pipe/-/cypress-pipe-2.0.0.tgz#577df7a70a8603d89a96dfe4092a605962181af8" integrity sha512-KW9s+bz4tFLucH3rBGfjW+Q12n7S4QpUSSyxiGrgPOfoHlbYWzAGB3H26MO0VTojqf9NVvfd5Kt0MH5XMgbfyg== -cypress-react-selector@^2.3.17: - version "2.3.17" - resolved "https://registry.yarnpkg.com/cypress-react-selector/-/cypress-react-selector-2.3.17.tgz#010382b486c4ec342ab61bcd121bb4ccd79e4590" - integrity sha512-yBi3wv5XUuzcYXearR0PN8lz0kMk44TOP4LVhwK1e4IU1fuWtlyVag1i+2eg0sdKRJ8VePEgmJhgZfOgd3VEgg== +cypress-react-selector@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cypress-react-selector/-/cypress-react-selector-3.0.0.tgz#e86018fffea07ba40c7a1f467a89b475a83cbcae" + integrity sha512-AQCgwbcMDkIdYcf6knvLxqzBnejahIbJPHqUhARi8k+QbM8sgUBDds98PaHJVMdPiX2J8RJjXHmUMPD8VerPSw== dependencies: resq "1.10.2" -cypress-real-events@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.7.0.tgz#ad6a78de33af3af0e6437f5c713e30691c44472c" - integrity sha512-iyXp07j0V9sG3YClVDcvHN2DAQDgr+EjTID82uWDw6OZBlU3pXEBqTMNYqroz3bxlb0k+F74U81aZwzMNaKyew== +cypress-real-events@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.7.1.tgz#8f430d67c29ea4f05b9c5b0311780120cbc9b935" + integrity sha512-/Bg15RgJ0SYsuXc6lPqH08x19z6j2vmhWN4wXfJqm3z8BTAFiK2MvipZPzxT8Z0jJP0q7kuniWrLIvz/i/8lCQ== -cypress-recurse@^1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/cypress-recurse/-/cypress-recurse-1.20.0.tgz#66c09d876ce1c143daa62fea222b5b80067a7fc9" - integrity sha512-8/gqot/XnVkSF8ssgn3zLRTfPw7Bum2tMIOxf6NO+Wqk0MBQdd4NPNVCObllZmmviLsGmF6ZXwlbXZ8TYvD6dw== +cypress-recurse@^1.23.0: + version "1.23.0" + resolved "https://registry.yarnpkg.com/cypress-recurse/-/cypress-recurse-1.23.0.tgz#f87334747516de6737bc4708754e8f429057bc6d" + integrity sha512-CAsdvynhuR3SUEXVJRO2jBEnZRJ6nJp7nMXHwzV4UQq9Lap3Bj72AwcJK0cl51fJXcTaGDXYTQQ9zvGe3TyaQA== -cypress@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-9.6.1.tgz#a7d6b5a53325b3dc4960181f5800a5ade0f085eb" - integrity sha512-ECzmV7pJSkk+NuAhEw6C3D+RIRATkSb2VAHXDY6qGZbca/F9mv5pPsj2LO6Ty6oIFVBTrwCyL9agl28MtJMe2g== +cypress@^10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.7.0.tgz#2d37f8b9751c6de33ee48639cb7e67a2ce593231" + integrity sha512-gTFvjrUoBnqPPOu9Vl5SBHuFlzx/Wxg/ZXIz2H4lzoOLFelKeF7mbwYUOzgzgF0oieU2WhJAestQdkgwJMMTvQ== dependencies: "@cypress/request" "^2.88.10" "@cypress/xvfb" "^1.2.4" @@ -12930,20 +12731,6 @@ debug@4.3.1: dependencies: ms "2.1.2" -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - -debug@4.3.3: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== - dependencies: - ms "2.1.2" - debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" @@ -13211,16 +12998,6 @@ deprecation@^2.0.0, deprecation@^2.3.1: resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -deps-sort@^2.0.0, deps-sort@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.1.tgz#9dfdc876d2bcec3386b6829ac52162cda9fa208d" - integrity sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw== - dependencies: - JSONStream "^1.0.3" - shasum-object "^1.0.0" - subarg "^1.0.0" - through2 "^2.0.0" - des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" @@ -13279,7 +13056,7 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" -detective@^5.0.2, detective@^5.2.0: +detective@^5.0.2: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== @@ -13455,7 +13232,7 @@ dom-walk@^0.1.0: resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= -domain-browser@^1.1.1, domain-browser@^1.2.0: +domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== @@ -13595,7 +13372,7 @@ dpdm@3.5.0: typescript "^3.5.3" yargs "^13.3.0" -duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4: +duplexer2@~0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= @@ -14556,11 +14333,6 @@ events@^1.0.2: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= -events@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" - integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== - events@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -15573,7 +15345,7 @@ geojson-vt@^3.2.1: resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-3.2.1.tgz#f8adb614d2c1d3f6ee7c4265cad4bbf3ad60c8b7" integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg== -get-assigned-identifiers@^1.1.0, get-assigned-identifiers@^1.2.0: +get-assigned-identifiers@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" integrity sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ== @@ -15795,7 +15567,7 @@ glob@^6.0.4: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0, glob@~7.2.0: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0, glob@~7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -16568,11 +16340,6 @@ html@1.0.0: dependencies: concat-stream "^1.4.7" -htmlescape@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" - integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= - htmlparser2@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78" @@ -16881,7 +16648,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -16906,13 +16673,6 @@ ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== -inline-source-map@~0.6.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" - integrity sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU= - dependencies: - source-map "~0.5.3" - inline-style-parser@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" @@ -16966,22 +16726,6 @@ inquirer@^8.2.3: through "^2.3.6" wrap-ansi "^7.0.0" -insert-module-globals@^7.0.0, insert-module-globals@^7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.1.tgz#d5e33185181a4e1f33b15f7bf100ee91890d5cb3" - integrity sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg== - dependencies: - JSONStream "^1.0.3" - acorn-node "^1.5.2" - combine-source-map "^0.8.0" - concat-stream "^1.6.1" - is-buffer "^1.1.0" - path-is-absolute "^1.0.1" - process "~0.11.0" - through2 "^2.0.0" - undeclared-identifiers "^1.1.2" - xtend "^4.0.0" - install-artifact-from-github@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.0.tgz#cab6ff821976b8a35b0c079da19a727c90381a40" @@ -17171,7 +16915,7 @@ is-boolean-object@^1.0.1, is-boolean-object@^1.1.0: dependencies: call-bind "^1.0.0" -is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.1: +is-buffer@^1.0.2, is-buffer@^1.1.5, is-buffer@~1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -17313,11 +17057,6 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e" integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g== -is-generator-function@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" - integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== - is-glob@^3.0.0, is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -18586,13 +18325,6 @@ json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stable-stringify@~0.0.0: - version "0.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" - integrity sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U= - dependencies: - jsonify "~0.0.0" - json-stringify-pretty-compact@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-1.2.0.tgz#0bc316b5e6831c07041fc35612487fb4e9ab98b8" @@ -18844,14 +18576,6 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== -labeled-stream-splicer@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz#42a41a16abcd46fd046306cf4f2c3576fffb1c21" - integrity sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw== - dependencies: - inherits "^2.0.1" - stream-splicer "^2.0.0" - language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -19140,11 +18864,6 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= - lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -19235,11 +18954,6 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.memoize@~3.0.3: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" - integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= - lodash.merge@4.6.2, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -19986,7 +19700,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== @@ -20173,27 +19887,6 @@ mock-fs@^5.1.2: resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-5.1.2.tgz#6fa486e06d00f8793a8d2228de980eff93ce6db7" integrity sha512-YkjQkdLulFrz0vD4BfNQdQRVmgycXTV7ykuHMlyv+C8WCHazpkiQRDthwa02kSyo8wKnY9wRptHfQLgmf0eR+A== -module-deps@^6.2.3: - version "6.2.3" - resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-6.2.3.tgz#15490bc02af4b56cf62299c7c17cba32d71a96ee" - integrity sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA== - dependencies: - JSONStream "^1.0.3" - browser-resolve "^2.0.0" - cached-path-relative "^1.0.2" - concat-stream "~1.6.0" - defined "^1.0.0" - detective "^5.2.0" - duplexer2 "^0.1.2" - inherits "^2.0.1" - parents "^1.0.0" - readable-stream "^2.0.2" - resolve "^1.4.0" - stream-combiner2 "^1.1.1" - subarg "^1.0.0" - through2 "^2.0.0" - xtend "^4.0.0" - module-details-from-path@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" @@ -21201,7 +20894,7 @@ original-url@^1.2.3: dependencies: forwarded-parse "^2.1.0" -os-browserify@^0.3.0, os-browserify@~0.3.0: +os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= @@ -21244,13 +20937,6 @@ ospath@^1.2.2: resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= -outpipe@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/outpipe/-/outpipe-1.1.1.tgz#50cf8616365e87e031e29a5ec9339a3da4725fa2" - integrity sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I= - dependencies: - shell-quote "^1.4.2" - overlayscrollbars@^1.13.1: version "1.13.1" resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-1.13.1.tgz#0b840a88737f43a946b9d87875a2f9e421d0338a" @@ -21462,13 +21148,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parents@^1.0.0, parents@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" - integrity sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E= - dependencies: - path-platform "~0.11.15" - parse-asn1@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" @@ -21562,12 +21241,12 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-browserify@0.0.1, path-browserify@~0.0.0: +path-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== -path-browserify@^1.0.0, path-browserify@^1.0.1: +path-browserify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== @@ -21587,7 +21266,7 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: +path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= @@ -21612,11 +21291,6 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-platform@~0.11.15: - version "0.11.15" - resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" - integrity sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I= - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -22424,7 +22098,7 @@ process-on-spawn@^1.0.0: dependencies: fromentries "^1.2.0" -process@^0.11.10, process@~0.11.0: +process@^0.11.10: version "0.11.10" resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= @@ -22676,7 +22350,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4, punycode@^1.3.2: +punycode@^1.2.4: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -22742,7 +22416,7 @@ query-string@^6.13.2: split-on-first "^1.0.0" strict-uri-encode "^2.0.0" -querystring-es3@^0.2.0, querystring-es3@~0.2.0: +querystring-es3@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= @@ -23543,13 +23217,6 @@ read-installed@~4.0.3: optionalDependencies: graceful-fs "^4.1.2" -read-only-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" - integrity sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A= - dependencies: - readable-stream "^2.0.2" - read-package-json@^2.0.0, read-package-json@^2.0.10: version "2.1.1" resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" @@ -23621,7 +23288,7 @@ readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0 isarray "0.0.1" string_decoder "~0.10.x" -"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: +"readable-stream@2 || 3", readable-stream@3, readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -24243,7 +23910,7 @@ resolve@1.1.7: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.9.0: +resolve@^1.1.5, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2, resolve@^1.9.0: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -24854,7 +24521,7 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: +sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== @@ -24898,21 +24565,6 @@ sharp@^0.30.1: tar-fs "^2.1.1" tunnel-agent "^0.6.0" -shasum-object@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shasum-object/-/shasum-object-1.0.0.tgz#0b7b74ff5b66ecf9035475522fa05090ac47e29e" - integrity sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg== - dependencies: - fast-safe-stringify "^2.0.7" - -shasum@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" - integrity sha1-5wEjENj0F/TetXEhUOVni4euVl8= - dependencies: - json-stable-stringify "~0.0.0" - sha.js "~2.4.4" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -24937,11 +24589,6 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.4.2, shell-quote@^1.6.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" - integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== - shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" @@ -25241,7 +24888,7 @@ source-map@0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" integrity sha1-dc449SvwczxafwwRjYEzSiu19BI= -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -25568,7 +25215,7 @@ store2@^2.12.0: resolved "https://registry.yarnpkg.com/store2/-/store2-2.12.0.tgz#e1f1b7e1a59b6083b2596a8d067f6ee88fd4d3cf" integrity sha512-7t+/wpKLanLzSnQPX8WAcuLCCeuSHoWdQuh9SB3xD0kNOM38DNf+0Oa+wmvxmYueRzkmh6IcdKFtvTa+ecgPDw== -stream-browserify@^2.0.0, stream-browserify@^2.0.1: +stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== @@ -25576,14 +25223,6 @@ stream-browserify@^2.0.0, stream-browserify@^2.0.1: inherits "~2.0.1" readable-stream "^2.0.2" -stream-browserify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" - integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== - dependencies: - inherits "~2.0.4" - readable-stream "^3.5.0" - stream-chopper@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/stream-chopper/-/stream-chopper-3.0.1.tgz#73791ae7bf954c297d6683aec178648efc61dd75" @@ -25591,14 +25230,6 @@ stream-chopper@^3.0.1: dependencies: readable-stream "^3.0.6" -stream-combiner2@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" - integrity sha1-+02KFCDqNidk4hrUeAOXvry0HL4= - dependencies: - duplexer2 "~0.1.0" - readable-stream "^2.0.2" - stream-each@^1.1.0: version "1.2.3" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" @@ -25618,16 +25249,6 @@ stream-http@^2.7.2: to-arraybuffer "^1.0.0" xtend "^4.0.0" -stream-http@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" - integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.4" - readable-stream "^3.6.0" - xtend "^4.0.2" - stream-shift@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" @@ -25638,14 +25259,6 @@ stream-slicer@0.0.6: resolved "https://registry.yarnpkg.com/stream-slicer/-/stream-slicer-0.0.6.tgz#f86b2ac5c2440b7a0a87b71f33665c0788046138" integrity sha1-+GsqxcJEC3oKh7cfM2ZcB4gEYTg= -stream-splicer@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.1.tgz#0b13b7ee2b5ac7e0609a7463d83899589a363fcd" - integrity sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg== - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.2" - stream-to-async-iterator@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/stream-to-async-iterator/-/stream-to-async-iterator-0.2.0.tgz#bef5c885e9524f98b2fa5effecc357bd58483780" @@ -25980,13 +25593,6 @@ stylis@4.0.13: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== -subarg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" - integrity sha1-9izxdYHplrSPyWVpn1TAauJouNI= - dependencies: - minimist "^1.1.0" - success-symbol@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897" @@ -26130,13 +25736,6 @@ synchronous-promise@^2.0.15: resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.15.tgz#07ca1822b9de0001f5ff73595f3d08c4f720eb8e" integrity sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg== -syntax-error@^1.1.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" - integrity sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w== - dependencies: - acorn-node "^1.2.0" - tabbable@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.2.1.tgz#e3fda7367ddbb172dcda9f871c0fdb36d1c4cd9c" @@ -26431,13 +26030,6 @@ timed-out@^2.0.0: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" integrity sha1-84sK6B03R9YoAB9B2vxlKs5nHAo= -timers-browserify@^1.0.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" - integrity sha1-ycWLV1voQHN1y14kYtrO50NZ9B0= - dependencies: - process "~0.11.0" - timers-browserify@^2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.6.tgz#241e76927d9ca05f4d959819022f5b3664b64bae" @@ -26834,11 +26426,6 @@ tty-browserify@0.0.0: resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= -tty-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" - integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -26964,11 +26551,6 @@ uglify-js@^3.1.4, uglify-js@^3.14.3: resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.14.4.tgz#68756f17d1b90b9d289341736cb9a567d6882f90" integrity sha512-AbiSR44J0GoCeV81+oxcy/jDOElO2Bx3d0MfQCUShq7JRXaM4KtQopZsq2vFv8bCq2yMaGrw1FgygUd03RyRDA== -umd@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" - integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== - unbox-primitive@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" @@ -26992,17 +26574,6 @@ unc-path-regex@^0.1.2: resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= -undeclared-identifiers@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz#9254c1d37bdac0ac2b52de4b6722792d2a91e30f" - integrity sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw== - dependencies: - acorn-node "^1.3.0" - dash-ast "^1.0.0" - get-assigned-identifiers "^1.2.0" - simple-concat "^1.0.0" - xtend "^4.0.1" - undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -27378,7 +26949,7 @@ url-template@^2.0.8: resolved "https://registry.yarnpkg.com/url-template/-/url-template-2.0.8.tgz#fc565a3cccbff7730c775f5641f9555791439f21" integrity sha1-/FZaPMy/93MMd19WQflVV5FDnyE= -url@^0.11.0, url@~0.11.0: +url@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= @@ -27491,23 +27062,6 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@~0.10.1: - version "0.10.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" - integrity sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A== - dependencies: - inherits "2.0.3" - -util@~0.12.0: - version "0.12.2" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.2.tgz#54adb634c9e7c748707af2bf5a8c7ab640cbba2b" - integrity sha512-XE+MkWQvglYa+IOfBt5UFG93EmncEMP23UqpgDvVZVFBPxwmkK10QRp6pgU4xICPnWRf/t0zPv4noYSUq9gqUQ== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - safe-buffer "^5.1.2" - utila@^0.4.0, utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" @@ -28051,7 +27605,7 @@ vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.0: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vm-browserify@^1.0.0, vm-browserify@^1.0.1: +vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== @@ -28093,19 +27647,6 @@ warning@^4.0.2: dependencies: loose-envify "^1.0.0" -watchify@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/watchify/-/watchify-4.0.0.tgz#53b002d51e7b0eb640b851bb4de517a689973392" - integrity sha512-2Z04dxwoOeNxa11qzWumBTgSAohTC0+ScuY7XMenPnH+W2lhTcpEOJP4g2EIG/SWeLadPk47x++Yh+8BqPM/lA== - dependencies: - anymatch "^3.1.0" - browserify "^17.0.0" - chokidar "^3.4.0" - defined "^1.0.0" - outpipe "^1.1.0" - through2 "^4.0.2" - xtend "^4.0.2" - watchpack-chokidar2@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" From 698717d7a49be0bec976d05d8df98175b47e9065 Mon Sep 17 00:00:00 2001 From: Byron Hulcher Date: Tue, 13 Sep 2022 12:29:35 -0400 Subject: [PATCH 125/144] Revert "[Enterprise Search] Use connector scheduling for crawler (#140268)" (#140434) This reverts commit ad0b42781b975e38ea3223e785a7d6006c8746ad. Co-authored-by: Dmitriy Burlutskiy --- .../enterprise_search/common/types/indices.ts | 6 +----- .../connector/connector_scheduling.tsx | 4 ++-- .../components/search_index/search_index.tsx | 3 ++- .../utils/indices.test.ts | 15 --------------- .../enterprise_search_content/utils/indices.ts | 11 ----------- 5 files changed, 5 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/enterprise_search/common/types/indices.ts b/x-pack/plugins/enterprise_search/common/types/indices.ts index 78831e16150046..d047ec9ba36d74 100644 --- a/x-pack/plugins/enterprise_search/common/types/indices.ts +++ b/x-pack/plugins/enterprise_search/common/types/indices.ts @@ -36,13 +36,9 @@ export interface ElasticsearchIndex { export interface ConnectorIndex extends ElasticsearchIndex { connector: Connector; } -export interface ConnectorCrawlerIndex extends ElasticsearchIndex { - connector: Connector; - crawler: Crawler; -} export interface CrawlerIndex extends ElasticsearchIndex { - connector?: Connector; crawler: Crawler; + connector?: Connector; } export interface ElasticsearchIndexWithPrivileges extends ElasticsearchIndex { diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx index 9c22ecd8572ef8..ca9a415c4c958d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_scheduling.tsx @@ -34,7 +34,7 @@ import { UpdateConnectorSchedulingApiLogic } from '../../../api/connector/update import { SEARCH_INDEX_TAB_PATH } from '../../../routes'; import { IngestionStatus } from '../../../types'; -import { isConnectorIndex, isConnectorCrawlerIndex } from '../../../utils/indices'; +import { isConnectorIndex } from '../../../utils/indices'; import { IndexViewLogic } from '../index_view_logic'; @@ -61,7 +61,7 @@ export const ConnectorSchedulingComponent: React.FC = () => { frequency: schedulingInput?.interval ? cronToFrequency(schedulingInput.interval) : 'HOUR', }); - if (!isConnectorIndex(index) && !isConnectorCrawlerIndex(index)) { + if (!isConnectorIndex(index)) { return <>; } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx index b998fa5d10db2a..58494595ad2e40 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx @@ -32,6 +32,7 @@ import { IndexCreatedCallout } from './components/index_created_callout/callout' import { IndexCreatedCalloutLogic } from './components/index_created_callout/callout_logic'; import { ConnectorConfiguration } from './connector/connector_configuration'; import { ConnectorSchedulingComponent } from './connector/connector_scheduling'; +import { AutomaticCrawlScheduler } from './crawler/automatic_crawl_scheduler/automatic_crawl_scheduler'; import { CrawlCustomSettingsFlyout } from './crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout'; import { SearchIndexDomainManagement } from './crawler/domain_management/domain_management'; import { SearchIndexDocuments } from './documents'; @@ -117,7 +118,7 @@ export const SearchIndex: React.FC = () => { }), }, { - content: , + content: , id: SearchIndexTabId.SCHEDULING, name: i18n.translate('xpack.enterpriseSearch.content.searchIndex.schedulingTabLabel', { defaultMessage: 'Scheduling', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts index b023aff4b9e085..ce6e443a250259 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.test.ts @@ -23,7 +23,6 @@ import { getLastUpdated, indexToViewIndex, isConnectorIndex, - isConnectorCrawlerIndex, isCrawlerIndex, isApiIndex, isConnectorViewIndex, @@ -145,20 +144,6 @@ describe('Indices util functions', () => { expect(isConnectorIndex(apiIndex)).toEqual(false); }); }); - describe('isConnectorCrawlerIndex', () => { - it('should return false for connector indices', () => { - expect(isConnectorCrawlerIndex(connectorIndex)).toEqual(false); - }); - it('should return false for connector-crawler indices', () => { - expect(isConnectorCrawlerIndex(connectorCrawlerIndex)).toEqual(true); - }); - it('should return false for crawler indices', () => { - expect(isConnectorCrawlerIndex(crawlerIndex)).toEqual(false); - }); - it('should return false for API indices', () => { - expect(isConnectorCrawlerIndex(apiIndex)).toEqual(false); - }); - }); describe('isCrawlerIndex', () => { it('should return true for crawler indices', () => { expect(isCrawlerIndex(crawlerIndex)).toEqual(true); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts index 540ad2b2db69e2..9a17f7fe84f4dd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts @@ -13,7 +13,6 @@ import { ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE } from '../../../../co import { SyncStatus, ConnectorStatus } from '../../../../common/types/connectors'; import { ConnectorIndex, - ConnectorCrawlerIndex, CrawlerIndex, ElasticsearchIndexWithIngestion, } from '../../../../common/types/indices'; @@ -37,16 +36,6 @@ export function isConnectorIndex( ); } -export function isConnectorCrawlerIndex( - index: ElasticsearchIndexWithIngestion | undefined -): index is ConnectorCrawlerIndex { - const crawlerIndex = index as CrawlerIndex; - return ( - !!crawlerIndex?.connector && - crawlerIndex.connector.service_type === ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE - ); -} - export function isCrawlerIndex( index: ElasticsearchIndexWithIngestion | undefined ): index is CrawlerIndex { From 63fd2ce6568277a6154b8c1bbcd4933d96a26586 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 13 Sep 2022 10:43:22 -0600 Subject: [PATCH 126/144] [Maps] fix map app crashing on file upload request timeout (#139760) * [Maps] fix GeoJSON upload fails * remove console.log statement * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * replace slowConnection with uploadSize * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * convert back to switch Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../geo_upload_form/geo_upload_form.tsx | 50 ++++++++++++++++--- .../public/components/geo_upload_wizard.tsx | 9 ++++ .../components/import_complete_view.tsx | 21 +++++--- .../geo/abstract_geo_file_importer.tsx | 8 ++- .../file_upload/public/importer/geo/types.ts | 1 + 5 files changed, 73 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/file_upload/public/components/geo_upload_form/geo_upload_form.tsx b/x-pack/plugins/file_upload/public/components/geo_upload_form/geo_upload_form.tsx index 43dde2580b66d5..05b6c6244810f3 100644 --- a/x-pack/plugins/file_upload/public/components/geo_upload_form/geo_upload_form.tsx +++ b/x-pack/plugins/file_upload/public/components/geo_upload_form/geo_upload_form.tsx @@ -6,7 +6,15 @@ */ import React, { ChangeEvent, Component } from 'react'; -import { EuiForm, EuiFormRow, EuiSelect } from '@elastic/eui'; +import { + EuiForm, + EuiFormRow, + EuiSpacer, + EuiSelect, + EuiSwitch, + EuiSwitchEvent, + EuiToolTip, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ES_FIELD_TYPES } from '@kbn/data-plugin/public'; import { GeoFilePicker, OnFileSelectParameters } from './geo_file_picker'; @@ -28,12 +36,14 @@ interface Props { geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE; indexName: string; indexNameError?: string; + smallChunks: boolean; onFileClear: () => void; onFileSelect: (onFileSelectParameters: OnFileSelectParameters) => void; onGeoFieldTypeSelect: (geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE) => void; onIndexNameChange: (name: string, error?: string) => void; onIndexNameValidationStart: () => void; onIndexNameValidationEnd: () => void; + onSmallChunksChange: (smallChunks: boolean) => void; } interface State { @@ -96,6 +106,10 @@ export class GeoUploadForm extends Component { ); }; + _onSmallChunksChange = (event: EuiSwitchEvent) => { + this.props.onSmallChunksChange(event.target.checked); + }; + _renderGeoFieldTypeSelect() { return this.state.hasFile && this.state.isPointsOnly ? ( { {this._renderGeoFieldTypeSelect()} {this.state.hasFile ? ( - + <> + + + + + + + + ) : null} ); diff --git a/x-pack/plugins/file_upload/public/components/geo_upload_wizard.tsx b/x-pack/plugins/file_upload/public/components/geo_upload_wizard.tsx index adbce777a49425..0c7f09c56f36f4 100644 --- a/x-pack/plugins/file_upload/public/components/geo_upload_wizard.tsx +++ b/x-pack/plugins/file_upload/public/components/geo_upload_wizard.tsx @@ -40,6 +40,7 @@ interface State { indexNameError?: string; dataViewResp?: object; phase: PHASE; + smallChunks: boolean; } export class GeoUploadWizard extends Component { @@ -52,6 +53,7 @@ export class GeoUploadWizard extends Component importStatus: '', indexName: '', phase: PHASE.CONFIGURE, + smallChunks: false, }; componentDidMount() { @@ -146,6 +148,7 @@ export class GeoUploadWizard extends Component this.setState({ importStatus: getWritingToIndexMsg(0), }); + this._geoFileImporter.setSmallChunks(this.state.smallChunks); const importResults = await this._geoFileImporter.import( initializeImportResp.id, this.state.indexName, @@ -281,6 +284,10 @@ export class GeoUploadWizard extends Component } }; + _onSmallChunksChange = (smallChunks: boolean) => { + this.setState({ smallChunks }); + }; + render() { if (this.state.phase === PHASE.IMPORT) { return ( @@ -311,10 +318,12 @@ export class GeoUploadWizard extends Component indexNameError={this.state.indexNameError} onFileClear={this._onFileClear} onFileSelect={this._onFileSelect} + smallChunks={this.state.smallChunks} onGeoFieldTypeSelect={this._onGeoFieldTypeSelect} onIndexNameChange={this._onIndexNameChange} onIndexNameValidationStart={this.props.disableImportBtn} onIndexNameValidationEnd={this.props.enableImportBtn} + onSmallChunksChange={this._onSmallChunksChange} /> ); } diff --git a/x-pack/plugins/file_upload/public/components/import_complete_view.tsx b/x-pack/plugins/file_upload/public/components/import_complete_view.tsx index 5ec4e6f0ddf375..46f566eb27e2e6 100644 --- a/x-pack/plugins/file_upload/public/components/import_complete_view.tsx +++ b/x-pack/plugins/file_upload/public/components/import_complete_view.tsx @@ -128,13 +128,20 @@ export class ImportCompleteView extends Component { } if (!this.props.importResults || !this.props.importResults.success) { - const errorMsg = - this.props.importResults && this.props.importResults.error - ? i18n.translate('xpack.fileUpload.importComplete.uploadFailureMsgErrorBlock', { - defaultMessage: 'Error: {reason}', - values: { reason: this.props.importResults.error.error.reason }, - }) - : ''; + let reason: string | undefined; + if (this.props.importResults?.error?.body?.message) { + // Display http request error message + reason = this.props.importResults.error.body.message; + } else if (this.props.importResults?.error?.error?.reason) { + // Display elasticxsearch request error message + reason = this.props.importResults.error.error.reason; + } + const errorMsg = reason + ? i18n.translate('xpack.fileUpload.importComplete.uploadFailureMsgErrorBlock', { + defaultMessage: 'Error: {reason}', + values: { reason }, + }) + : ''; return ( ; renderEditor(onChange: () => void): ReactNode; setGeoFieldType(geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE): void; + setSmallChunks(smallChunks: boolean): void; } From e167ae0f0df13192aa1e6ce295778e42cc1de39f Mon Sep 17 00:00:00 2001 From: spalger Date: Tue, 13 Sep 2022 12:16:47 -0500 Subject: [PATCH 127/144] remove invalid document ids --- dev_docs/operations/operations_landing.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev_docs/operations/operations_landing.mdx b/dev_docs/operations/operations_landing.mdx index 3a80faa90c501f..88e4be9eb93a30 100644 --- a/dev_docs/operations/operations_landing.mdx +++ b/dev_docs/operations/operations_landing.mdx @@ -71,8 +71,6 @@ layout: landing { pageId: "kibDevDocsOpsDevCliRunner" }, { pageId: "kibDevDocsOpsGetRepoFiles" }, { pageId: "kibDevDocsOpsRepoSourceClassifier" }, - { pageId: "kibDevDocsOpsJsonc" }, - { pageId: "kibDevDocsOpsKibanaManifestParser" }, { pageId: "kibDevDocsOpsKibanaManifestSchema" }, { pageId: "kibDevDocsOpsManagedVscodeConfig" }, { pageId: "kibDevDocsOpsManagedVscodeConfigCli" }, From d9b7c3fe5089c7c5916105ba1878b64e4ead54ec Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 13 Sep 2022 13:25:44 -0400 Subject: [PATCH 128/144] [Synthetics] prevent decryption errors from causing the entire suite of monitors to fail syncing (#140549) * synthetics - prevent decryption errors from causing the entire suite of monitors to fail syncing * adjust decryption error catching logic * Update x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts * Update x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../synthetics_service/synthetics_service.ts | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts index 55c0b7f16e14af..908584a7be03ec 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts @@ -434,17 +434,36 @@ export class SyntheticsService { const start = performance.now(); - const monitors: Array> = await Promise.all( - encryptedMonitors.map((monitor) => - encryptedClient.getDecryptedAsInternalUser( - syntheticsMonitor.name, - monitor.id, - { - namespace: monitor.namespaces?.[0], - } + const monitors: Array> = ( + await Promise.all( + encryptedMonitors.map( + (monitor) => + new Promise((resolve) => { + encryptedClient + .getDecryptedAsInternalUser( + syntheticsMonitor.name, + monitor.id, + { + namespace: monitor.namespaces?.[0], + } + ) + .then((decryptedMonitor) => resolve(decryptedMonitor)) + .catch((e) => { + this.logger.error(e); + sendErrorTelemetryEvents(this.logger, this.server.telemetry, { + reason: 'Failed to decrypt monitor', + message: e?.message, + type: 'runTaskError', + code: e?.code, + status: e.status, + kibanaVersion: this.server.kibanaVersion, + }); + resolve(null); + }); + }) ) ) - ); + ).filter((monitor) => monitor !== null) as Array>; const end = performance.now(); const duration = end - start; From 0ecd3fae50a72ff60aa2fd077eb48d5b2528bab9 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 13 Sep 2022 14:07:52 -0400 Subject: [PATCH 129/144] [Synthetics] remove hydrating saved objects (#140545) * synthetics - remove hydrating saved objects * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * remove logic to set url back to empty string * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../routes/monitor_cruds/edit_monitor.ts | 6 +- .../hydrate_saved_object.test.ts | 125 -------------- .../hydrate_saved_object.ts | 158 ------------------ .../synthetics_service/synthetics_service.ts | 10 -- 4 files changed, 1 insertion(+), 298 deletions(-) delete mode 100644 x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts delete mode 100644 x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts diff --git a/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts b/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts index 832c4322a28668..12b958fa3c67d4 100644 --- a/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts +++ b/x-pack/plugins/synthetics/server/routes/monitor_cruds/edit_monitor.ts @@ -20,7 +20,6 @@ import { SyntheticsMonitorWithSecrets, SyntheticsMonitor, ConfigKey, - FormMonitorType, } from '../../../common/runtime_types'; import { SyntheticsRestApiRouteFactory } from '../../legacy_uptime/routes/types'; import { API_URLS } from '../../../common/constants'; @@ -146,10 +145,7 @@ export const syncEditedMonitor = async ({ const editedSOPromise = savedObjectsClient.update( syntheticsMonitorType, previousMonitor.id, - monitorWithRevision.type === 'browser' && - monitorWithRevision[ConfigKey.FORM_MONITOR_TYPE] !== FormMonitorType.SINGLE - ? { ...monitorWithRevision, urls: '' } - : monitorWithRevision + monitorWithRevision ); const editSyncPromise = syntheticsMonitorClient.editMonitor( diff --git a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts deleted file mode 100644 index c2c0412d940c5d..00000000000000 --- a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.test.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { hydrateSavedObjects } from './hydrate_saved_object'; -import { DecryptedSyntheticsMonitorSavedObject } from '../../common/types'; -import { UptimeServerSetup } from '../legacy_uptime/lib/adapters'; -import { getUptimeESMockClient } from '../legacy_uptime/lib/requests/test_helpers'; -import { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; - -import moment from 'moment'; - -describe('hydrateSavedObjects', () => { - const { uptimeEsClient: mockUptimeEsClient, esClient: mockEsClient } = getUptimeESMockClient(); - - const mockMonitorTemplate = { - id: 'my-mock-monitor', - attributes: { - type: 'browser', - name: 'Test Browser Monitor 01', - }, - }; - - const serverMock: UptimeServerSetup = { - uptimeEsClient: mockUptimeEsClient, - authSavedObjectsClient: { - bulkUpdate: jest.fn(), - }, - } as unknown as UptimeServerSetup; - - const toKibanaResponse = (hits: Array<{ _source: Record }>) => ({ - body: { hits: { hits } }, - }); - - beforeEach(() => { - mockUptimeEsClient.baseESClient.security.hasPrivileges = jest - .fn() - .mockResolvedValue({ has_all_requested: true }); - }); - - it.each([['browser'], ['http'], ['tcp']])( - 'hydrates missing data for %s monitors', - async (type) => { - const time = moment(); - const monitor = { - ...mockMonitorTemplate, - attributes: { ...mockMonitorTemplate.attributes, type }, - updated_at: moment(time).subtract(1, 'hour').toISOString(), - } as DecryptedSyntheticsMonitorSavedObject; - - const monitors: DecryptedSyntheticsMonitorSavedObject[] = [monitor]; - - mockEsClient.search.mockResolvedValue( - toKibanaResponse([ - { - _source: { - config_id: monitor.id, - '@timestamp': moment(time).toISOString(), - url: { port: 443, full: 'https://example.com' }, - }, - }, - ]) as unknown as SearchResponse - ); - - await hydrateSavedObjects({ monitors, server: serverMock }); - - expect(serverMock.authSavedObjectsClient?.bulkUpdate).toHaveBeenCalledWith([ - { - ...monitor, - attributes: { - ...monitor.attributes, - 'url.port': 443, - urls: 'https://example.com', - }, - }, - ]); - } - ); - - it.each([['browser'], ['http'], ['tcp']])( - 'does not hydrate when the user does not have permissions', - async (type) => { - const time = moment(); - const monitor = { - ...mockMonitorTemplate, - attributes: { ...mockMonitorTemplate.attributes, type }, - updated_at: moment(time).subtract(1, 'hour').toISOString(), - } as DecryptedSyntheticsMonitorSavedObject; - - const monitors: DecryptedSyntheticsMonitorSavedObject[] = [monitor]; - - mockUptimeEsClient.baseESClient.security.hasPrivileges = jest - .fn() - .mockResolvedValue({ has_all_requested: false }); - - mockEsClient.search.mockResolvedValue( - toKibanaResponse([ - { - _source: { - config_id: monitor.id, - '@timestamp': moment(time).toISOString(), - url: { port: 443, full: 'https://example.com' }, - }, - }, - ]) as unknown as SearchResponse - ); - - await hydrateSavedObjects({ monitors, server: serverMock }); - - expect(serverMock.authSavedObjectsClient?.bulkUpdate).not.toHaveBeenCalledWith([ - { - ...monitor, - attributes: { - ...monitor.attributes, - 'url.port': 443, - urls: 'https://example.com', - }, - }, - ]); - } - ); -}); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts b/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts deleted file mode 100644 index 9f4158248d6bfe..00000000000000 --- a/x-pack/plugins/synthetics/server/synthetics_service/hydrate_saved_object.ts +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import moment from 'moment'; -import type { SecurityIndexPrivilege } from '@elastic/elasticsearch/lib/api/types'; -import { UptimeESClient } from '../legacy_uptime/lib/lib'; -import { UptimeServerSetup } from '../legacy_uptime/lib/adapters'; -import { DecryptedSyntheticsMonitorSavedObject } from '../../common/types'; -import { SyntheticsMonitor, MonitorFields, Ping } from '../../common/runtime_types'; -import { SYNTHETICS_INDEX_PATTERN } from '../../common/constants'; - -export const hydrateSavedObjects = async ({ - monitors, - server, -}: { - monitors: DecryptedSyntheticsMonitorSavedObject[]; - server: UptimeServerSetup; -}) => { - try { - const { uptimeEsClient } = server; - if (!uptimeEsClient) { - return; - } - - const { has_all_requested: hasAllPrivileges } = - await uptimeEsClient.baseESClient.security.hasPrivileges({ - body: { - index: [ - { - names: ['synthetics-*'], - privileges: ['read'] as SecurityIndexPrivilege[], - }, - ], - }, - }); - - if (!hasAllPrivileges) { - return; - } - - const missingInfoIds: string[] = monitors - .filter((monitor) => { - const isBrowserMonitor = monitor.attributes.type === 'browser'; - const isHTTPMonitor = monitor.attributes.type === 'http'; - const isTCPMonitor = monitor.attributes.type === 'tcp'; - - const monitorAttributes = monitor.attributes as MonitorFields; - const isMissingUrls = !monitorAttributes || !monitorAttributes.urls; - const isMissingPort = !monitorAttributes || !monitorAttributes['url.port']; - - const isEnrichableBrowserMonitor = isBrowserMonitor && (isMissingUrls || isMissingPort); - const isEnrichableHttpMonitor = isHTTPMonitor && isMissingPort; - const isEnrichableTcpMonitor = isTCPMonitor && isMissingPort; - - return isEnrichableBrowserMonitor || isEnrichableHttpMonitor || isEnrichableTcpMonitor; - }) - .map(({ id }) => id); - - if (missingInfoIds.length > 0 && server.uptimeEsClient) { - const esDocs: Ping[] = await fetchSampleMonitorDocuments( - server.uptimeEsClient, - missingInfoIds - ); - - const updatedObjects: DecryptedSyntheticsMonitorSavedObject[] = []; - monitors - .filter((monitor) => missingInfoIds.includes(monitor.id)) - .forEach((monitor) => { - let resultAttributes: SyntheticsMonitor = monitor.attributes; - - let isUpdated = false; - - esDocs.forEach((doc) => { - // to make sure the document is ingested after the latest update of the monitor - const documentIsAfterLatestUpdate = moment(monitor.updated_at).isBefore( - moment(doc.timestamp) - ); - if (!documentIsAfterLatestUpdate) return monitor; - if (doc.config_id !== monitor.id) return monitor; - - if (doc.url?.full) { - isUpdated = true; - resultAttributes = { ...resultAttributes, urls: doc.url?.full }; - } - - if (doc.url?.port) { - isUpdated = true; - resultAttributes = { ...resultAttributes, ['url.port']: doc.url?.port }; - } - }); - if (isUpdated) { - updatedObjects.push({ - ...monitor, - attributes: resultAttributes, - } as DecryptedSyntheticsMonitorSavedObject); - } - }); - - await server.authSavedObjectsClient?.bulkUpdate( - updatedObjects - ); - } - } catch (e) { - server.logger.error(e); - } -}; - -const fetchSampleMonitorDocuments = async (esClient: UptimeESClient, configIds: string[]) => { - const data = await esClient.search( - { - body: { - query: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: 'now-15m', - lt: 'now', - }, - }, - }, - { - terms: { - config_id: configIds, - }, - }, - { - exists: { - field: 'summary', - }, - }, - { - bool: { - minimum_should_match: 1, - should: [{ exists: { field: 'url.full' } }, { exists: { field: 'url.port' } }], - }, - }, - ], - }, - }, - _source: ['url', 'config_id', '@timestamp'], - collapse: { - field: 'config_id', - }, - }, - }, - 'getHydrateQuery', - SYNTHETICS_INDEX_PATTERN - ); - return data.body.hits.hits.map( - ({ _source: doc }) => ({ ...(doc as any), timestamp: (doc as any)['@timestamp'] } as Ping) - ); -}; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts index 908584a7be03ec..60c98bd5cc1c9d 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/synthetics_service.ts @@ -42,8 +42,6 @@ import { HeartbeatConfig, } from '../../common/runtime_types'; import { getServiceLocations } from './get_service_locations'; -import { hydrateSavedObjects } from './hydrate_saved_object'; -import { DecryptedSyntheticsMonitorSavedObject } from '../../common/types'; import { normalizeSecrets } from './utils/secrets'; @@ -475,14 +473,6 @@ export class SyntheticsService { monitors: monitors.length, }); - if (this.indexTemplateExists) { - // without mapping, querying won't make sense - hydrateSavedObjects({ - monitors: monitors as unknown as DecryptedSyntheticsMonitorSavedObject[], - server: this.server, - }); - } - return (monitors ?? []).map((monitor) => { const attributes = monitor.attributes as unknown as MonitorFields; return formatHeartbeatRequest({ From ef184c4fb79bf40799f5c2c744a5205f2d06b102 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 13 Sep 2022 11:19:13 -0700 Subject: [PATCH 130/144] [8.5][Onboarding][Endpoint and Cloud Security] Create event filters attached to the policy (#140139) --- .../endpoint/endpoint_app_context_services.ts | 6 + .../server/fleet_integration/constants.ts | 17 +++ .../fleet_integration.test.ts | 8 +- .../fleet_integration/fleet_integration.ts | 58 +++++++- .../handlers/create_default_policy.ts | 139 +++++++++++++++++- .../handlers/create_event_filters.ts | 104 +++++++++++++ .../handlers/validate_integration_config.ts | 90 ++++++++++++ .../server/fleet_integration/types.ts | 30 ++++ 8 files changed, 445 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/constants.ts create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/types.ts diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index 3571ffca63b073..59deaae59f4504 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -22,6 +22,7 @@ import { getPackagePolicyCreateCallback, getPackagePolicyUpdateCallback, getPackagePolicyDeleteCallback, + getPackagePolicyPostCreateCallback, } from '../fleet_integration/fleet_integration'; import type { ManifestManager } from './services/artifacts'; import type { ConfigType } from '../config'; @@ -119,6 +120,11 @@ export class EndpointAppContextService { ) ); + registerIngestCallback( + 'packagePolicyPostCreate', + getPackagePolicyPostCreateCallback(logger, exceptionListsClient) + ); + registerIngestCallback( 'packagePolicyUpdate', getPackagePolicyUpdateCallback( diff --git a/x-pack/plugins/security_solution/server/fleet_integration/constants.ts b/x-pack/plugins/security_solution/server/fleet_integration/constants.ts new file mode 100644 index 00000000000000..cefa99722fa3e3 --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/constants.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. + */ + +/** + * Endpoint Security integration presets. + * The default endpoint policy configuration can be overrided based on the preset. + */ + +export const ENDPOINT_CONFIG_PRESET_NGAV = 'NGAV'; +export const ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL = 'EDREssential'; +export const ENDPOINT_CONFIG_PRESET_EDR_COMPLETE = 'EDRComplete'; + +export const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts index 0c6611acb77e09..664abac92db93e 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts @@ -82,6 +82,7 @@ describe('ingest_integration tests ', () => { enabled: true, streams: [], config: { + integration_config: {}, policy: { value: policyFactory() }, artifact_manifest: { value: manifest }, }, @@ -247,8 +248,13 @@ describe('ingest_integration tests ', () => { expect(manifestManager.pushArtifacts).not.toHaveBeenCalled(); expect(manifestManager.commit).not.toHaveBeenCalled(); }); - }); + it.todo('should override policy config with endpoint settings'); + it.todo('should override policy config with cloud settings'); + }); + describe('package policy post create callback', () => { + it.todo('should create Event Filters given valid parameter on integration config'); + }); describe('package policy update callback (when the license is below platinum)', () => { beforeEach(() => { licenseEmitter.next(Gold); // set license level to gold diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts index e7f21716541cce..f383778b764d2d 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts @@ -12,10 +12,14 @@ import type { PostPackagePolicyCreateCallback, PostPackagePolicyDeleteCallback, PutPackagePolicyUpdateCallback, + PostPackagePolicyPostCreateCallback, } from '@kbn/fleet-plugin/server'; -import type { NewPackagePolicy, UpdatePackagePolicy } from '@kbn/fleet-plugin/common'; - +import type { + NewPackagePolicy, + PackagePolicy, + UpdatePackagePolicy, +} from '@kbn/fleet-plugin/common'; import type { NewPolicyData, PolicyConfig } from '../../common/endpoint/types'; import type { LicenseService } from '../../common/license'; import type { ManifestManager } from '../endpoint/services'; @@ -24,10 +28,14 @@ import { installPrepackagedRules } from './handlers/install_prepackaged_rules'; import { createPolicyArtifactManifest } from './handlers/create_policy_artifact_manifest'; import { createDefaultPolicy } from './handlers/create_default_policy'; import { validatePolicyAgainstLicense } from './handlers/validate_policy_against_license'; +import { validateIntegrationConfig } from './handlers/validate_integration_config'; import { removePolicyFromArtifacts } from './handlers/remove_policy_from_artifacts'; import type { FeatureUsageService } from '../endpoint/services/feature_usage/service'; import type { EndpointMetadataService } from '../endpoint/services/metadata'; import { notifyProtectionFeatureUsage } from './notify_protection_feature_usage'; +import type { AnyPolicyCreateConfig } from './types'; +import { ENDPOINT_INTEGRATION_CONFIG_KEY } from './constants'; +import { createEventFilters } from './handlers/create_event_filters'; const isEndpointPackagePolicy = ( packagePolicy: T @@ -56,6 +64,23 @@ export const getPackagePolicyCreateCallback = ( return newPackagePolicy; } + // Optional endpoint integration configuration + let endpointIntegrationConfig; + + // Check if has endpoint integration configuration input + const integrationConfigInput = newPackagePolicy?.inputs?.find( + (input) => input.type === ENDPOINT_INTEGRATION_CONFIG_KEY + )?.config?._config; + + if (integrationConfigInput?.value) { + // The cast below is needed in order to ensure proper typing for the + // Elastic Defend integration configuration + endpointIntegrationConfig = integrationConfigInput.value as AnyPolicyCreateConfig; + + // Validate that the Elastic Defend integration config is valid + validateIntegrationConfig(endpointIntegrationConfig, logger); + } + // In this callback we are handling an HTTP request to the fleet plugin. Since we use // code from the security_solution plugin to handle it (installPrepackagedRules), // we need to build the context that is native to security_solution and pass it there. @@ -81,7 +106,7 @@ export const getPackagePolicyCreateCallback = ( ]); // Add the default endpoint security policy - const defaultPolicyValue = createDefaultPolicy(licenseService); + const defaultPolicyValue = createDefaultPolicy(licenseService, endpointIntegrationConfig); return { // We cast the type here so that any changes to the Endpoint @@ -93,6 +118,9 @@ export const getPackagePolicyCreateCallback = ( enabled: true, streams: [], config: { + integration_config: endpointIntegrationConfig + ? { value: endpointIntegrationConfig } + : {}, artifact_manifest: { value: manifestValue, }, @@ -136,6 +164,30 @@ export const getPackagePolicyUpdateCallback = ( }; }; +export const getPackagePolicyPostCreateCallback = ( + logger: Logger, + exceptionsClient: ExceptionListClient | undefined +): PostPackagePolicyPostCreateCallback => { + return async (packagePolicy: PackagePolicy): Promise => { + // We only care about Endpoint package policies + if (!exceptionsClient || !isEndpointPackagePolicy(packagePolicy)) { + return packagePolicy; + } + + const integrationConfig = packagePolicy?.inputs[0].config?.integration_config; + + if (integrationConfig && integrationConfig?.value?.eventFilters !== undefined) { + createEventFilters( + logger, + exceptionsClient, + integrationConfig.value.eventFilters, + packagePolicy + ); + } + return packagePolicy; + }; +}; + export const getPackagePolicyDeleteCallback = ( exceptionsClient: ExceptionListClient | undefined ): PostPackagePolicyDeleteCallback => { diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts index ab01467e75ceeb..47b4840665e640 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts @@ -11,13 +11,146 @@ import { } from '../../../common/endpoint/models/policy_config'; import type { LicenseService } from '../../../common/license/license'; import { isAtLeast } from '../../../common/license/license'; +import { ProtectionModes } from '../../../common/endpoint/types'; import type { PolicyConfig } from '../../../common/endpoint/types'; +import type { + AnyPolicyCreateConfig, + PolicyCreateCloudConfig, + PolicyCreateEndpointConfig, +} from '../types'; +import { ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL, ENDPOINT_CONFIG_PRESET_NGAV } from '../constants'; /** - * Create the default endpoint policy based on the current license + * Create the default endpoint policy based on the current license and configuration type */ -export const createDefaultPolicy = (licenseService: LicenseService): PolicyConfig => { - return isAtLeast(licenseService.getLicenseInformation(), 'platinum') +export const createDefaultPolicy = ( + licenseService: LicenseService, + config: AnyPolicyCreateConfig | undefined +): PolicyConfig => { + const policy = isAtLeast(licenseService.getLicenseInformation(), 'platinum') ? policyConfigFactory() : policyConfigFactoryWithoutPaidFeatures(); + + if (config?.type === 'cloud') { + return getCloudPolicyWithIntegrationConfig(policy, config); + } + + return getEndpointPolicyWithIntegrationConfig(policy, config); +}; + +/** + * Set all keys of the given object to false + */ +const falsyObjectKeys = >(obj: T): T => { + return Object.keys(obj).reduce((accumulator, key) => { + return { ...accumulator, [key]: false }; + }, {} as T); +}; + +/** + * Retrieve policy for endpoint based on the preset selected in the endpoint integration config + */ +const getEndpointPolicyWithIntegrationConfig = ( + policy: PolicyConfig, + config: PolicyCreateEndpointConfig | undefined +): PolicyConfig => { + const isEDREssential = config?.endpointConfig?.preset === ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL; + + if (config?.endpointConfig?.preset === ENDPOINT_CONFIG_PRESET_NGAV || isEDREssential) { + const events = { + process: true, + file: isEDREssential, + network: isEDREssential, + }; + + return { + ...policy, + linux: { + ...policy.linux, + events: { + ...falsyObjectKeys(policy.linux.events), + ...events, + }, + }, + windows: { + ...policy.windows, + events: { + ...falsyObjectKeys(policy.windows.events), + ...events, + }, + }, + mac: { + ...policy.mac, + events: { + ...falsyObjectKeys(policy.mac.events), + ...events, + }, + }, + }; + } + + return policy; +}; + +/** + * Retrieve policy for cloud based on the on the cloud integration config + */ +const getCloudPolicyWithIntegrationConfig = ( + policy: PolicyConfig, + config: PolicyCreateCloudConfig +): PolicyConfig => { + /** + * Check if the protection is supported, then retrieve Behavior Protection mode based on cloud settings + */ + const getBehaviorProtectionMode = () => { + if (!policy.linux.behavior_protection.supported) { + return ProtectionModes.off; + } + + return config.cloudConfig.preventions.behavior_protection + ? ProtectionModes.prevent + : ProtectionModes.off; + }; + + const protections = { + // Disabling memory_protection, since it's not supported on Cloud integrations + memory_protection: { + supported: false, + mode: ProtectionModes.off, + }, + malware: { + ...policy.linux.malware, + // Malware protection mode based on cloud settings + mode: config.cloudConfig.preventions.malware ? ProtectionModes.prevent : ProtectionModes.off, + }, + behavior_protection: { + ...policy.linux.behavior_protection, + mode: getBehaviorProtectionMode(), + }, + }; + + return { + ...policy, + linux: { + ...policy.linux, + ...protections, + events: { + ...policy.linux.events, + session_data: true, + }, + }, + windows: { + ...policy.windows, + ...protections, + // Disabling ransomware protection, since it's not supported on Cloud integrations + ransomware: { + supported: false, + mode: ProtectionModes.off, + }, + }, + mac: { + ...policy.mac, + ...protections, + }, + }; }; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts new file mode 100644 index 00000000000000..70854e31f69563 --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts @@ -0,0 +1,104 @@ +/* + * 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 uuid from 'uuid'; +import { i18n } from '@kbn/i18n'; +import { + ENDPOINT_EVENT_FILTERS_LIST_ID, + ENDPOINT_EVENT_FILTERS_LIST_NAME, + ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION, +} from '@kbn/securitysolution-list-constants'; +import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; +import { SavedObjectsErrorHelpers } from '@kbn/core/server'; +import type { Logger } from '@kbn/core/server'; +import type { PackagePolicy } from '@kbn/fleet-plugin/common'; +import type { ExceptionListClient } from '@kbn/lists-plugin/server'; +import { wrapErrorIfNeeded } from '../../endpoint/utils'; +import type { PolicyCreateEventFilters } from '../types'; + +const PROCESS_INTERACTIVE_ECS_FIELD = 'process.entry_leader.interactive'; + +/** + * Create the Event Filter list if not exists and Create Event Filters for the Elastic Defend integration. + */ +export const createEventFilters = async ( + logger: Logger, + exceptionsClient: ExceptionListClient, + eventFilters: PolicyCreateEventFilters, + packagePolicy: PackagePolicy +): Promise => { + if (!eventFilters?.nonInteractiveSession) { + return; + } + try { + // Attempt to Create the Event Filter List. It won't create the list if it already exists. + // So we can skip the validation and ignore the conflict error + await exceptionsClient.createExceptionList({ + name: ENDPOINT_EVENT_FILTERS_LIST_NAME, + namespaceType: 'agnostic', + description: ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION, + listId: ENDPOINT_EVENT_FILTERS_LIST_ID, + type: ExceptionListTypeEnum.ENDPOINT_EVENTS, + immutable: false, + meta: undefined, + tags: [], + version: 1, + }); + } catch (err) { + // Ignoring error 409 (Conflict) + if (!SavedObjectsErrorHelpers.isConflictError(err)) { + logger.error(`Error creating Event Filter List: ${wrapErrorIfNeeded(err)}`); + return; + } + } + + createNonInteractiveSessionEventFilter(logger, exceptionsClient, packagePolicy); +}; + +/** + * Create an Event Filter for non-interactive sessions and attach it to the policy + */ +export const createNonInteractiveSessionEventFilter = ( + logger: Logger, + exceptionsClient: ExceptionListClient, + packagePolicy: PackagePolicy +): void => { + try { + exceptionsClient.createExceptionListItem({ + listId: ENDPOINT_EVENT_FILTERS_LIST_ID, + description: i18n.translate( + 'xpack.securitySolution.fleetIntegration.elasticDefend.eventFilter.nonInteractiveSessions.description', + { + defaultMessage: 'Event filter for Cloud Security. Created by Elastic Defend integration.', + } + ), + name: i18n.translate( + 'xpack.securitySolution.fleetIntegration.elasticDefend.eventFilter.nonInteractiveSessions.name', + { + defaultMessage: 'Non-interactive Sessions', + } + ), + // Attach to the created policy + tags: [`policy:${packagePolicy.id}`], + osTypes: ['linux'], + type: 'simple', + namespaceType: 'agnostic', + entries: [ + { + field: PROCESS_INTERACTIVE_ECS_FIELD, + operator: 'included', + type: 'match', + value: 'false', + }, + ], + itemId: uuid.v4(), + meta: [], + comments: [], + }); + } catch (err) { + logger.error(`Error creating Event Filter: ${wrapErrorIfNeeded(err)}`); + } +}; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts new file mode 100644 index 00000000000000..d56dd6a02d4cde --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts @@ -0,0 +1,90 @@ +/* + * 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 type { Logger } from '@kbn/core/server'; +import { + ENDPOINT_CONFIG_PRESET_EDR_COMPLETE, + ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL, + ENDPOINT_CONFIG_PRESET_NGAV, +} from '../constants'; +import type { + AnyPolicyCreateConfig, + PolicyCreateCloudConfig, + PolicyCreateEndpointConfig, +} from '../types'; + +// The `statusCode` is used by Fleet API handler to ensure that the proper HTTP code is used in the API response +type THROW_ERROR = Error & { statusCode?: number }; + +const throwError = (message: string): never => { + const error: THROW_ERROR = new Error(message); + error.statusCode = 403; + throw error; +}; + +const validateEndpointIntegrationConfig = ( + config: PolicyCreateEndpointConfig, + logger: Logger +): void => { + if (!config?.endpointConfig?.preset) { + logger.warn('missing endpointConfig preset'); + throwError('invalid endpointConfig preset'); + } + if ( + ![ + ENDPOINT_CONFIG_PRESET_NGAV, + ENDPOINT_CONFIG_PRESET_EDR_COMPLETE, + ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL, + ].includes(config.endpointConfig.preset) + ) { + logger.warn(`invalid endpointConfig preset: ${config.endpointConfig.preset}`); + throwError('invalid endpointConfig preset'); + } +}; +const validateCloudIntegrationConfig = (config: PolicyCreateCloudConfig, logger: Logger): void => { + if (!config?.cloudConfig?.preventions) { + logger.warn( + 'missing cloudConfig preventions: {preventions : malware: true / false, behavior_protection: true / false}' + ); + throwError('invalid value for cloudConfig: missing preventions '); + } + if (typeof config.cloudConfig.preventions.behavior_protection !== 'boolean') { + logger.warn( + `invalid value for cloudConfig preventions behavior_protection: ${config.cloudConfig.preventions.behavior_protection}` + ); + throwError('invalid value for cloudConfig preventions behavior_protection'); + } + if (typeof config.cloudConfig.preventions.malware !== 'boolean') { + logger.warn( + `invalid value for cloudConfig preventions malware: ${config.cloudConfig.preventions.malware}` + ); + throwError('invalid value for cloudConfig preventions malware'); + } + if (!config?.eventFilters) { + logger.warn( + `eventFilters is required for cloud integration: {eventFilters : nonInteractiveSession: true / false}` + ); + throwError('eventFilters is required for cloud integration'); + } + if (typeof config.eventFilters?.nonInteractiveSession !== 'boolean') { + logger.warn( + `missing or invalid value for eventFilters nonInteractiveSession: ${config.eventFilters?.nonInteractiveSession}` + ); + throwError('invalid value for eventFilters nonInteractiveSession'); + } +}; + +export const validateIntegrationConfig = (config: AnyPolicyCreateConfig, logger: Logger): void => { + if (config.type === 'endpoint') { + validateEndpointIntegrationConfig(config, logger); + } else if (config.type === 'cloud') { + validateCloudIntegrationConfig(config, logger); + } else { + logger.warn(`Invalid integration config type ${config}`); + throwError('Invalid integration config type'); + } +}; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/types.ts b/x-pack/plugins/security_solution/server/fleet_integration/types.ts new file mode 100644 index 00000000000000..2d012832f1ae2f --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/types.ts @@ -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. + */ + +export interface PolicyCreateEndpointConfig { + type: 'endpoint'; + endpointConfig: { + preset: 'NGAV' | 'EDREssential' | 'EDRComplete'; + }; +} + +export interface PolicyCreateEventFilters { + nonInteractiveSession?: boolean; +} + +export interface PolicyCreateCloudConfig { + type: 'cloud'; + cloudConfig: { + preventions: { + malware: boolean; + behavior_protection: boolean; + }; + }; + eventFilters?: PolicyCreateEventFilters; +} + +export type AnyPolicyCreateConfig = PolicyCreateEndpointConfig | PolicyCreateCloudConfig; From 940f108aeb744b3e6bb3e795d85328f428715651 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 13 Sep 2022 11:21:38 -0700 Subject: [PATCH 131/144] [Filters] Remove filter validation for ad-hoc data views (#139431) * No longer disable filters for invalid data views * Fix failing test * Fix functional test * Remove unused translations Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../filter_bar/filter_item/filter_item.tsx | 46 +------------------ .../dashboard/group2/dashboard_filter_bar.ts | 4 +- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 5 files changed, 3 insertions(+), 53 deletions(-) diff --git a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx index 32601f4590558f..3f70a57708b465 100644 --- a/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx +++ b/src/plugins/unified_search/public/filter_bar/filter_item/filter_item.tsx @@ -29,7 +29,6 @@ import { } from '@kbn/data-plugin/public'; import { FilterEditor } from '../filter_editor/filter_editor'; import { FilterView } from '../filter_view'; -import { getIndexPatterns } from '../../services'; import { FilterPanelOption } from '../../types'; export interface FilterItemProps { @@ -67,7 +66,6 @@ export const FILTER_EDITOR_WIDTH = 800; export function FilterItem(props: FilterItemProps) { const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [indexPatternExists, setIndexPatternExists] = useState(undefined); const [renderedComponent, setRenderedComponent] = useState('menu'); const { id, filter, indexPatterns, hiddenPanelOptions, readOnly = false } = props; @@ -77,31 +75,6 @@ export function FilterItem(props: FilterItemProps) { } }, [isPopoverOpen]); - useEffect(() => { - const index = props.filter.meta.index; - let isSubscribed = true; - if (index) { - getIndexPatterns() - .get(index) - .then((indexPattern) => { - if (isSubscribed) { - setIndexPatternExists(!!indexPattern); - } - }) - .catch(() => { - if (isSubscribed) { - setIndexPatternExists(false); - } - }); - } else if (isSubscribed) { - // Allow filters without an index pattern and don't validate them. - setIndexPatternExists(true); - } - return () => { - isSubscribed = false; - }; - }, [props.filter.meta.index]); - function handleBadgeClick(e: MouseEvent) { if (e.shiftKey) { onToggleDisabled(); @@ -297,22 +270,7 @@ export function FilterItem(props: FilterItemProps) { return label; } - if (indexPatternExists === false) { - label.status = FILTER_ITEM_ERROR; - label.title = props.intl.formatMessage({ - id: 'unifiedSearch.filter.filterBar.labelErrorText', - defaultMessage: `Error`, - }); - label.message = props.intl.formatMessage( - { - id: 'unifiedSearch.filter.filterBar.labelErrorInfo', - defaultMessage: 'Index pattern {indexPattern} not found', - }, - { - indexPattern: filter.meta.index, - } - ); - } else if (isFilterApplicable()) { + if (isFilterApplicable()) { try { label.title = getDisplayValueFromFilter(filter, indexPatterns); } catch (e) { @@ -343,8 +301,6 @@ export function FilterItem(props: FilterItemProps) { return label; } - // Don't render until we know if the index pattern is valid - if (indexPatternExists === undefined) return null; const valueLabelConfig = getValueLabel(); // Disable errored filters and re-render diff --git a/test/functional/apps/dashboard/group2/dashboard_filter_bar.ts b/test/functional/apps/dashboard/group2/dashboard_filter_bar.ts index f2476f7516611c..1244e179f7f6a1 100644 --- a/test/functional/apps/dashboard/group2/dashboard_filter_bar.ts +++ b/test/functional/apps/dashboard/group2/dashboard_filter_bar.ts @@ -224,8 +224,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.dashboard.loadSavedDashboard('dashboard with bad filters'); }); - it('filter with non-existent index pattern renders in error mode', async function () { - const hasBadFieldFilter = await filterBar.hasFilter('name', 'error', false); + it('filter with non-existent index pattern renders if it matches a field', async function () { + const hasBadFieldFilter = await filterBar.hasFilter('name', 'moo', false); expect(hasBadFieldFilter).to.be(true); }); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index c10ded1c3e623d..92e1e27c900417 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -4953,7 +4953,6 @@ "uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesFilterPlaceholderText": "Variables de filtre", "uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesHelpLinkText": "Aide", "unifiedSearch.filter.filterBar.filterItemBadgeIconAriaLabel": "Supprimer {filter}", - "unifiedSearch.filter.filterBar.labelErrorInfo": "Modèle d'indexation {indexPattern} introuvable", "unifiedSearch.filter.filterBar.labelWarningInfo": "Le champ {fieldName} n'existe pas dans la vue en cours.", "unifiedSearch.kueryAutocomplete.andOperatorDescription": "Nécessite que {bothArguments} soient ''vrai''.", "unifiedSearch.kueryAutocomplete.equalOperatorDescription": "{equals} une certaine valeur", @@ -5026,7 +5025,6 @@ "unifiedSearch.filter.filterBar.includeFilterButtonLabel": "Inclure les résultats", "unifiedSearch.filter.filterBar.indexPatternSelectPlaceholder": "Sélectionner une vue de données", "unifiedSearch.filter.filterBar.invalidDateFormatProvidedErrorMessage": "Format de date non valide fourni", - "unifiedSearch.filter.filterBar.labelErrorText": "Erreur", "unifiedSearch.filter.filterBar.labelWarningText": "Avertissement", "unifiedSearch.filter.filterBar.negatedFilterPrefix": "NON ", "unifiedSearch.filter.filterBar.pinFilterButtonLabel": "Épingler dans toutes les applications", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a6a6a929da9dd5..30b6982a95d39b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4950,7 +4950,6 @@ "uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesFilterPlaceholderText": "変数をフィルター", "uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesHelpLinkText": "ヘルプ", "unifiedSearch.filter.filterBar.filterItemBadgeIconAriaLabel": "{filter}を削除", - "unifiedSearch.filter.filterBar.labelErrorInfo": "インデックスパターン{indexPattern}が見つかりません", "unifiedSearch.filter.filterBar.labelWarningInfo": "フィールド{fieldName}は現在のビューに存在しません", "unifiedSearch.kueryAutocomplete.andOperatorDescription": "{bothArguments} が true であることを条件とする", "unifiedSearch.kueryAutocomplete.equalOperatorDescription": "一部の値に{equals}", @@ -5023,7 +5022,6 @@ "unifiedSearch.filter.filterBar.includeFilterButtonLabel": "結果を含める", "unifiedSearch.filter.filterBar.indexPatternSelectPlaceholder": "データビューを選択", "unifiedSearch.filter.filterBar.invalidDateFormatProvidedErrorMessage": "無効な日付形式が指定されました", - "unifiedSearch.filter.filterBar.labelErrorText": "エラー", "unifiedSearch.filter.filterBar.labelWarningText": "警告", "unifiedSearch.filter.filterBar.negatedFilterPrefix": "NOT ", "unifiedSearch.filter.filterBar.pinFilterButtonLabel": "すべてのアプリにピン付け", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index bd0b538fd94dde..8ecac17ffa0a3f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4956,7 +4956,6 @@ "uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesFilterPlaceholderText": "筛选变量", "uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.urlTemplateVariablesHelpLinkText": "帮助", "unifiedSearch.filter.filterBar.filterItemBadgeIconAriaLabel": "删除 {filter}", - "unifiedSearch.filter.filterBar.labelErrorInfo": "找不到索引模式 {indexPattern}", "unifiedSearch.filter.filterBar.labelWarningInfo": "当前视图中不存在字段 {fieldName}", "unifiedSearch.kueryAutocomplete.andOperatorDescription": "需要{bothArguments}为 true", "unifiedSearch.kueryAutocomplete.equalOperatorDescription": "{equals}某一值", @@ -5029,7 +5028,6 @@ "unifiedSearch.filter.filterBar.includeFilterButtonLabel": "包括结果", "unifiedSearch.filter.filterBar.indexPatternSelectPlaceholder": "选择数据视图", "unifiedSearch.filter.filterBar.invalidDateFormatProvidedErrorMessage": "提供的日期格式无效", - "unifiedSearch.filter.filterBar.labelErrorText": "错误", "unifiedSearch.filter.filterBar.labelWarningText": "警告", "unifiedSearch.filter.filterBar.negatedFilterPrefix": "非 ", "unifiedSearch.filter.filterBar.pinFilterButtonLabel": "在所有应用上固定", From 4c6dc3c86d60dc69ce9e9c6e780bdb0b6fa2c9a2 Mon Sep 17 00:00:00 2001 From: Pierre Gayvallet Date: Tue, 13 Sep 2022 20:54:09 +0200 Subject: [PATCH 132/144] Migrate client-side `coreApp` domain to packages (#140242) * move sass-loader related files to src/core/public/styles * create empty packages * Move all the things * fix optimizer integration tests * add kibana.jsonc files * fix bazel build * [CI] Auto-commit changed files from 'node scripts/generate codeowners' * fix usages * fix mocked service name Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 2 + package.json | 4 + packages/BUILD.bazel | 4 + .../core-apps-browser-internal/BUILD.bazel | 137 ++++++++++++++++++ .../apps/core-apps-browser-internal/README.md | 3 + .../apps/core-apps-browser-internal/index.ts | 10 ++ .../core-apps-browser-internal/jest.config.js | 13 ++ .../core-apps-browser-internal/kibana.jsonc | 7 + .../core-apps-browser-internal/package.json | 9 ++ .../src}/core_app.ts | 16 +- .../src}/errors/error_application.test.ts | 0 .../src}/errors/error_application.tsx | 0 .../src}/errors/index.ts | 0 .../src}/errors/public_base_url.test.tsx | 0 .../src}/errors/public_base_url.tsx | 3 +- .../src}/errors/url_overflow.test.ts | 0 .../src}/errors/url_overflow.tsx | 0 .../src}/errors/url_overflow_ui.tsx | 0 .../core-apps-browser-internal/src/index.ts | 11 ++ .../__snapshots__/metric_tiles.test.tsx.snap | 0 .../__snapshots__/server_status.test.tsx.snap | 0 .../__snapshots__/status_table.test.tsx.snap | 0 .../src}/status/components/index.ts | 0 .../status/components/metric_tiles.test.tsx | 0 .../src}/status/components/metric_tiles.tsx | 0 .../status/components/server_status.test.tsx | 0 .../src}/status/components/server_status.tsx | 0 .../status/components/status_badge.test.tsx | 0 .../src}/status/components/status_badge.tsx | 0 .../status/components/status_expanded_row.tsx | 0 .../src}/status/components/status_section.tsx | 0 .../status/components/status_table.test.tsx | 0 .../src}/status/components/status_table.tsx | 0 .../status/components/version_header.test.tsx | 0 .../src}/status/components/version_header.tsx | 0 .../src}/status/index.ts | 0 .../src}/status/lib/format_number.test.ts | 0 .../src}/status/lib/format_number.ts | 0 .../src}/status/lib/index.ts | 0 .../src}/status/lib/load_status.test.ts | 0 .../src}/status/lib/load_status.ts | 2 +- .../src}/status/lib/status_level.test.ts | 0 .../src}/status/lib/status_level.ts | 0 .../src}/status/render_app.tsx | 0 .../src}/status/status_app.tsx | 0 .../core-apps-browser-internal/tsconfig.json | 19 +++ .../apps/core-apps-browser-mocks/BUILD.bazel | 115 +++++++++++++++ .../apps/core-apps-browser-mocks/README.md | 4 + .../apps/core-apps-browser-mocks}/index.ts | 3 +- .../core-apps-browser-mocks/jest.config.js | 13 ++ .../apps/core-apps-browser-mocks/kibana.jsonc | 7 + .../apps/core-apps-browser-mocks/package.json | 9 ++ .../src}/core_app.mock.ts | 7 +- .../apps/core-apps-browser-mocks/src/index.ts | 9 ++ .../core-apps-browser-mocks/tsconfig.json | 18 +++ .../core_app}/_globals_v7dark.scss | 0 .../core_app}/_globals_v7light.scss | 0 .../core_app}/_globals_v8dark.scss | 0 .../core_app}/_globals_v8light.scss | 0 .../basic_optimization.test.ts | 4 +- .../src/worker/webpack.config.ts | 7 +- src/core/public/core_system.test.mocks.ts | 8 +- src/core/public/core_system.ts | 6 +- src/core/public/index.ts | 2 +- src/core/public/styles/core_app/README.txt | 1 + .../core_app}/_globals_v8dark.scss | 0 .../core_app}/_globals_v8light.scss | 0 .../styles => styles/core_app}/_mixins.scss | 0 .../core_app/images/bg_bottom_branded.svg | 0 .../images/bg_bottom_branded_dark.svg | 0 .../core_app/images/bg_top_branded.svg | 0 .../core_app/images/bg_top_branded_dark.svg | 0 yarn.lock | 16 ++ 73 files changed, 445 insertions(+), 24 deletions(-) create mode 100644 packages/core/apps/core-apps-browser-internal/BUILD.bazel create mode 100644 packages/core/apps/core-apps-browser-internal/README.md create mode 100644 packages/core/apps/core-apps-browser-internal/index.ts create mode 100644 packages/core/apps/core-apps-browser-internal/jest.config.js create mode 100644 packages/core/apps/core-apps-browser-internal/kibana.jsonc create mode 100644 packages/core/apps/core-apps-browser-internal/package.json rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/core_app.ts (91%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/error_application.test.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/error_application.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/index.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/public_base_url.test.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/public_base_url.tsx (95%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/url_overflow.test.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/url_overflow.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/errors/url_overflow_ui.tsx (100%) create mode 100644 packages/core/apps/core-apps-browser-internal/src/index.ts rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/__snapshots__/metric_tiles.test.tsx.snap (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/__snapshots__/server_status.test.tsx.snap (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/__snapshots__/status_table.test.tsx.snap (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/index.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/metric_tiles.test.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/metric_tiles.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/server_status.test.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/server_status.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/status_badge.test.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/status_badge.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/status_expanded_row.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/status_section.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/status_table.test.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/status_table.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/version_header.test.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/components/version_header.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/index.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/lib/format_number.test.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/lib/format_number.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/lib/index.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/lib/load_status.test.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/lib/load_status.ts (99%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/lib/status_level.test.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/lib/status_level.ts (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/render_app.tsx (100%) rename {src/core/public/core_app => packages/core/apps/core-apps-browser-internal/src}/status/status_app.tsx (100%) create mode 100644 packages/core/apps/core-apps-browser-internal/tsconfig.json create mode 100644 packages/core/apps/core-apps-browser-mocks/BUILD.bazel create mode 100644 packages/core/apps/core-apps-browser-mocks/README.md rename {src/core/public/core_app => packages/core/apps/core-apps-browser-mocks}/index.ts (81%) create mode 100644 packages/core/apps/core-apps-browser-mocks/jest.config.js create mode 100644 packages/core/apps/core-apps-browser-mocks/kibana.jsonc create mode 100644 packages/core/apps/core-apps-browser-mocks/package.json rename {src/core/public/core_app => packages/core/apps/core-apps-browser-mocks/src}/core_app.mock.ts (77%) create mode 100644 packages/core/apps/core-apps-browser-mocks/src/index.ts create mode 100644 packages/core/apps/core-apps-browser-mocks/tsconfig.json rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{core_app/styles => styles/core_app}/_globals_v7dark.scss (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{core_app/styles => styles/core_app}/_globals_v7light.scss (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{core_app/styles => styles/core_app}/_globals_v8dark.scss (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{core_app/styles => styles/core_app}/_globals_v8light.scss (100%) create mode 100644 src/core/public/styles/core_app/README.txt rename src/core/public/{core_app/styles => styles/core_app}/_globals_v8dark.scss (100%) rename src/core/public/{core_app/styles => styles/core_app}/_globals_v8light.scss (100%) rename src/core/public/{core_app/styles => styles/core_app}/_mixins.scss (100%) rename src/core/public/{ => styles}/core_app/images/bg_bottom_branded.svg (100%) rename src/core/public/{ => styles}/core_app/images/bg_bottom_branded_dark.svg (100%) rename src/core/public/{ => styles}/core_app/images/bg_top_branded.svg (100%) rename src/core/public/{ => styles}/core_app/images/bg_top_branded_dark.svg (100%) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 89f74e669e9cf3..dbc10f3a6c41e2 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -658,6 +658,8 @@ packages/core/application/core-application-browser @elastic/kibana-core packages/core/application/core-application-browser-internal @elastic/kibana-core packages/core/application/core-application-browser-mocks @elastic/kibana-core packages/core/application/core-application-common @elastic/kibana-core +packages/core/apps/core-apps-browser-internal @elastic/kibana-core +packages/core/apps/core-apps-browser-mocks @elastic/kibana-core packages/core/base/core-base-browser-internal @elastic/kibana-core packages/core/base/core-base-browser-mocks @elastic/kibana-core packages/core/base/core-base-common @elastic/kibana-core diff --git a/package.json b/package.json index c8c1aa501b9814..4fa23bdb9ef47f 100644 --- a/package.json +++ b/package.json @@ -156,6 +156,8 @@ "@kbn/core-application-browser-internal": "link:bazel-bin/packages/core/application/core-application-browser-internal", "@kbn/core-application-browser-mocks": "link:bazel-bin/packages/core/application/core-application-browser-mocks", "@kbn/core-application-common": "link:bazel-bin/packages/core/application/core-application-common", + "@kbn/core-apps-browser-internal": "link:bazel-bin/packages/core/apps/core-apps-browser-internal", + "@kbn/core-apps-browser-mocks": "link:bazel-bin/packages/core/apps/core-apps-browser-mocks", "@kbn/core-base-browser-internal": "link:bazel-bin/packages/core/base/core-base-browser-internal", "@kbn/core-base-browser-mocks": "link:bazel-bin/packages/core/base/core-base-browser-mocks", "@kbn/core-base-common": "link:bazel-bin/packages/core/base/core-base-common", @@ -844,6 +846,8 @@ "@types/kbn__core-application-browser-internal": "link:bazel-bin/packages/core/application/core-application-browser-internal/npm_module_types", "@types/kbn__core-application-browser-mocks": "link:bazel-bin/packages/core/application/core-application-browser-mocks/npm_module_types", "@types/kbn__core-application-common": "link:bazel-bin/packages/core/application/core-application-common/npm_module_types", + "@types/kbn__core-apps-browser-internal": "link:bazel-bin/packages/core/apps/core-apps-browser-internal/npm_module_types", + "@types/kbn__core-apps-browser-mocks": "link:bazel-bin/packages/core/apps/core-apps-browser-mocks/npm_module_types", "@types/kbn__core-base-browser": "link:bazel-bin/packages/core/base/core-base-browser/npm_module_types", "@types/kbn__core-base-browser-internal": "link:bazel-bin/packages/core/base/core-base-browser-internal/npm_module_types", "@types/kbn__core-base-browser-mocks": "link:bazel-bin/packages/core/base/core-base-browser-mocks/npm_module_types", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index b898faee5fb07e..18c2202fb8d2cd 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -24,6 +24,8 @@ filegroup( "//packages/core/application/core-application-browser-internal:build", "//packages/core/application/core-application-browser-mocks:build", "//packages/core/application/core-application-common:build", + "//packages/core/apps/core-apps-browser-internal:build", + "//packages/core/apps/core-apps-browser-mocks:build", "//packages/core/base/core-base-browser-internal:build", "//packages/core/base/core-base-browser-mocks:build", "//packages/core/base/core-base-common:build", @@ -332,6 +334,8 @@ filegroup( "//packages/core/application/core-application-browser-internal:build_types", "//packages/core/application/core-application-browser-mocks:build_types", "//packages/core/application/core-application-common:build_types", + "//packages/core/apps/core-apps-browser-internal:build_types", + "//packages/core/apps/core-apps-browser-mocks:build_types", "//packages/core/base/core-base-browser-internal:build_types", "//packages/core/base/core-base-browser-mocks:build_types", "//packages/core/base/core-base-common:build_types", diff --git a/packages/core/apps/core-apps-browser-internal/BUILD.bazel b/packages/core/apps/core-apps-browser-internal/BUILD.bazel new file mode 100644 index 00000000000000..4ca5c1a1cf2af1 --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/BUILD.bazel @@ -0,0 +1,137 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-apps-browser-internal" +PKG_REQUIRE_NAME = "@kbn/core-apps-browser-internal" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/*.config.js", + "**/*.mock.*", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//react", + "@npm//react-dom", + "@npm//history", + "@npm//@elastic/eui", + "//packages/kbn-i18n", + "//packages/kbn-i18n-react", + "//packages/core/mount-utils/core-mount-utils-browser-internal", +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//@types/react", + "@npm//@types/react-dom", + "@npm//@types/history", + "@npm//@elastic/eui", + "//packages/kbn-i18n:npm_module_types", + "//packages/kbn-i18n-react:npm_module_types", + "//packages/core/base/core-base-browser-internal:npm_module_types", + "//packages/core/injected-metadata/core-injected-metadata-browser-internal:npm_module_types", + "//packages/core/doc-links/core-doc-links-browser:npm_module_types", + "//packages/core/http/core-http-browser:npm_module_types", + "//packages/core/ui-settings/core-ui-settings-browser:npm_module_types", + "//packages/core/notifications/core-notifications-browser:npm_module_types", + "//packages/core/application/core-application-browser:npm_module_types", + "//packages/core/application/core-application-browser-internal:npm_module_types", + "//packages/core/theme/core-theme-browser-internal:npm_module_types", + "//packages/core/mount-utils/core-mount-utils-browser-internal:npm_module_types", + "//packages/core/status/core-status-common-internal:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/apps/core-apps-browser-internal/README.md b/packages/core/apps/core-apps-browser-internal/README.md new file mode 100644 index 00000000000000..8412844a911df4 --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/README.md @@ -0,0 +1,3 @@ +# @kbn/core-apps-browser-internal + +This package contains the internal types and implementation of Core's `coreApps` service. diff --git a/packages/core/apps/core-apps-browser-internal/index.ts b/packages/core/apps/core-apps-browser-internal/index.ts new file mode 100644 index 00000000000000..35678cd2a19fd4 --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/index.ts @@ -0,0 +1,10 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { CoreAppsService, URL_MAX_LENGTH } from './src'; +export type { CoreAppsServiceSetupDeps, CoreAppsServiceStartDeps } from './src'; diff --git a/packages/core/apps/core-apps-browser-internal/jest.config.js b/packages/core/apps/core-apps-browser-internal/jest.config.js new file mode 100644 index 00000000000000..80df7f644eab5f --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/jest.config.js @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/apps/core-apps-browser-internal'], +}; diff --git a/packages/core/apps/core-apps-browser-internal/kibana.jsonc b/packages/core/apps/core-apps-browser-internal/kibana.jsonc new file mode 100644 index 00000000000000..552de143ce1dec --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-apps-browser-internal", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/apps/core-apps-browser-internal/package.json b/packages/core/apps/core-apps-browser-internal/package.json new file mode 100644 index 00000000000000..58262f9a7aaeb7 --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/package.json @@ -0,0 +1,9 @@ +{ + "name": "@kbn/core-apps-browser-internal", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "author": "Kibana Core", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/public/core_app/core_app.ts b/packages/core/apps/core-apps-browser-internal/src/core_app.ts similarity index 91% rename from src/core/public/core_app/core_app.ts rename to packages/core/apps/core-apps-browser-internal/src/core_app.ts index 7b4fd29011b9bd..e8a61de40bea2e 100644 --- a/src/core/public/core_app/core_app.ts +++ b/packages/core/apps/core-apps-browser-internal/src/core_app.ts @@ -25,14 +25,14 @@ import { } from './errors'; import { renderApp as renderStatusApp } from './status'; -export interface SetupDeps { +export interface CoreAppsServiceSetupDeps { application: InternalApplicationSetup; http: HttpSetup; injectedMetadata: InternalInjectedMetadataSetup; notifications: NotificationsSetup; } -export interface StartDeps { +export interface CoreAppsServiceStartDeps { application: InternalApplicationStart; docLinks: DocLinksStart; http: HttpStart; @@ -40,12 +40,12 @@ export interface StartDeps { uiSettings: IUiSettingsClient; } -export class CoreApp { +export class CoreAppsService { private stopHistoryListening?: UnregisterCallback; constructor(private readonly coreContext: CoreContext) {} - public setup({ application, http, injectedMetadata, notifications }: SetupDeps) { + public setup({ application, http, injectedMetadata, notifications }: CoreAppsServiceSetupDeps) { application.register(this.coreContext.coreId, { id: 'error', title: 'App Error', @@ -73,7 +73,13 @@ export class CoreApp { }); } - public start({ application, docLinks, http, notifications, uiSettings }: StartDeps) { + public start({ + application, + docLinks, + http, + notifications, + uiSettings, + }: CoreAppsServiceStartDeps) { if (!application.history) { return; } diff --git a/src/core/public/core_app/errors/error_application.test.ts b/packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts similarity index 100% rename from src/core/public/core_app/errors/error_application.test.ts rename to packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts diff --git a/src/core/public/core_app/errors/error_application.tsx b/packages/core/apps/core-apps-browser-internal/src/errors/error_application.tsx similarity index 100% rename from src/core/public/core_app/errors/error_application.tsx rename to packages/core/apps/core-apps-browser-internal/src/errors/error_application.tsx diff --git a/src/core/public/core_app/errors/index.ts b/packages/core/apps/core-apps-browser-internal/src/errors/index.ts similarity index 100% rename from src/core/public/core_app/errors/index.ts rename to packages/core/apps/core-apps-browser-internal/src/errors/index.ts diff --git a/src/core/public/core_app/errors/public_base_url.test.tsx b/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.test.tsx similarity index 100% rename from src/core/public/core_app/errors/public_base_url.test.tsx rename to packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.test.tsx diff --git a/src/core/public/core_app/errors/public_base_url.tsx b/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx similarity index 95% rename from src/core/public/core_app/errors/public_base_url.tsx rename to packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx index f86903f3c185fe..ec5f45930ce228 100644 --- a/src/core/public/core_app/errors/public_base_url.tsx +++ b/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx @@ -12,8 +12,9 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { DocLinksStart } from '@kbn/core-doc-links-browser'; +import type { HttpStart } from '@kbn/core-http-browser'; +import type { NotificationsStart } from '@kbn/core-notifications-browser'; import { mountReactNode } from '@kbn/core-mount-utils-browser-internal'; -import type { HttpStart, NotificationsStart } from '../..'; /** Only exported for tests */ export const MISSING_CONFIG_STORAGE_KEY = `core.warnings.publicBaseUrlMissingDismissed`; diff --git a/src/core/public/core_app/errors/url_overflow.test.ts b/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts similarity index 100% rename from src/core/public/core_app/errors/url_overflow.test.ts rename to packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts diff --git a/src/core/public/core_app/errors/url_overflow.tsx b/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.tsx similarity index 100% rename from src/core/public/core_app/errors/url_overflow.tsx rename to packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.tsx diff --git a/src/core/public/core_app/errors/url_overflow_ui.tsx b/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow_ui.tsx similarity index 100% rename from src/core/public/core_app/errors/url_overflow_ui.tsx rename to packages/core/apps/core-apps-browser-internal/src/errors/url_overflow_ui.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/index.ts b/packages/core/apps/core-apps-browser-internal/src/index.ts new file mode 100644 index 00000000000000..d0bb30144b7dbc --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/src/index.ts @@ -0,0 +1,11 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { CoreAppsService } from './core_app'; +export { URL_MAX_LENGTH } from './errors'; +export type { CoreAppsServiceSetupDeps, CoreAppsServiceStartDeps } from './core_app'; diff --git a/src/core/public/core_app/status/components/__snapshots__/metric_tiles.test.tsx.snap b/packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/metric_tiles.test.tsx.snap similarity index 100% rename from src/core/public/core_app/status/components/__snapshots__/metric_tiles.test.tsx.snap rename to packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/metric_tiles.test.tsx.snap diff --git a/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap b/packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/server_status.test.tsx.snap similarity index 100% rename from src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap rename to packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/server_status.test.tsx.snap diff --git a/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap b/packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/status_table.test.tsx.snap similarity index 100% rename from src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap rename to packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/status_table.test.tsx.snap diff --git a/src/core/public/core_app/status/components/index.ts b/packages/core/apps/core-apps-browser-internal/src/status/components/index.ts similarity index 100% rename from src/core/public/core_app/status/components/index.ts rename to packages/core/apps/core-apps-browser-internal/src/status/components/index.ts diff --git a/src/core/public/core_app/status/components/metric_tiles.test.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.test.tsx similarity index 100% rename from src/core/public/core_app/status/components/metric_tiles.test.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.test.tsx diff --git a/src/core/public/core_app/status/components/metric_tiles.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.tsx similarity index 100% rename from src/core/public/core_app/status/components/metric_tiles.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.tsx diff --git a/src/core/public/core_app/status/components/server_status.test.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/server_status.test.tsx similarity index 100% rename from src/core/public/core_app/status/components/server_status.test.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/server_status.test.tsx diff --git a/src/core/public/core_app/status/components/server_status.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/server_status.tsx similarity index 100% rename from src/core/public/core_app/status/components/server_status.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/server_status.tsx diff --git a/src/core/public/core_app/status/components/status_badge.test.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.test.tsx similarity index 100% rename from src/core/public/core_app/status/components/status_badge.test.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.test.tsx diff --git a/src/core/public/core_app/status/components/status_badge.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.tsx similarity index 100% rename from src/core/public/core_app/status/components/status_badge.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.tsx diff --git a/src/core/public/core_app/status/components/status_expanded_row.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/status_expanded_row.tsx similarity index 100% rename from src/core/public/core_app/status/components/status_expanded_row.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/status_expanded_row.tsx diff --git a/src/core/public/core_app/status/components/status_section.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/status_section.tsx similarity index 100% rename from src/core/public/core_app/status/components/status_section.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/status_section.tsx diff --git a/src/core/public/core_app/status/components/status_table.test.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/status_table.test.tsx similarity index 100% rename from src/core/public/core_app/status/components/status_table.test.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/status_table.test.tsx diff --git a/src/core/public/core_app/status/components/status_table.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/status_table.tsx similarity index 100% rename from src/core/public/core_app/status/components/status_table.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/status_table.tsx diff --git a/src/core/public/core_app/status/components/version_header.test.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/version_header.test.tsx similarity index 100% rename from src/core/public/core_app/status/components/version_header.test.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/version_header.test.tsx diff --git a/src/core/public/core_app/status/components/version_header.tsx b/packages/core/apps/core-apps-browser-internal/src/status/components/version_header.tsx similarity index 100% rename from src/core/public/core_app/status/components/version_header.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/components/version_header.tsx diff --git a/src/core/public/core_app/status/index.ts b/packages/core/apps/core-apps-browser-internal/src/status/index.ts similarity index 100% rename from src/core/public/core_app/status/index.ts rename to packages/core/apps/core-apps-browser-internal/src/status/index.ts diff --git a/src/core/public/core_app/status/lib/format_number.test.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.test.ts similarity index 100% rename from src/core/public/core_app/status/lib/format_number.test.ts rename to packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.test.ts diff --git a/src/core/public/core_app/status/lib/format_number.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.ts similarity index 100% rename from src/core/public/core_app/status/lib/format_number.ts rename to packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.ts diff --git a/src/core/public/core_app/status/lib/index.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/index.ts similarity index 100% rename from src/core/public/core_app/status/lib/index.ts rename to packages/core/apps/core-apps-browser-internal/src/status/lib/index.ts diff --git a/src/core/public/core_app/status/lib/load_status.test.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.test.ts similarity index 100% rename from src/core/public/core_app/status/lib/load_status.test.ts rename to packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.test.ts diff --git a/src/core/public/core_app/status/lib/load_status.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts similarity index 99% rename from src/core/public/core_app/status/lib/load_status.ts rename to packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts index 5a4b2b5907ea2c..c3ebd9923e2a81 100644 --- a/src/core/public/core_app/status/lib/load_status.ts +++ b/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts @@ -14,7 +14,7 @@ import type { StatusResponse, StatusInfoServiceStatus as ServiceStatus, } from '@kbn/core-status-common-internal'; -import type { DataType } from '.'; +import type { DataType } from './format_number'; interface MetricMeta { title: string; diff --git a/src/core/public/core_app/status/lib/status_level.test.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.test.ts similarity index 100% rename from src/core/public/core_app/status/lib/status_level.test.ts rename to packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.test.ts diff --git a/src/core/public/core_app/status/lib/status_level.ts b/packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.ts similarity index 100% rename from src/core/public/core_app/status/lib/status_level.ts rename to packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.ts diff --git a/src/core/public/core_app/status/render_app.tsx b/packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx similarity index 100% rename from src/core/public/core_app/status/render_app.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx diff --git a/src/core/public/core_app/status/status_app.tsx b/packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx similarity index 100% rename from src/core/public/core_app/status/status_app.tsx rename to packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx diff --git a/packages/core/apps/core-apps-browser-internal/tsconfig.json b/packages/core/apps/core-apps-browser-internal/tsconfig.json new file mode 100644 index 00000000000000..2249e2ee937617 --- /dev/null +++ b/packages/core/apps/core-apps-browser-internal/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [ + "jest", + "node", + "react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ] +} diff --git a/packages/core/apps/core-apps-browser-mocks/BUILD.bazel b/packages/core/apps/core-apps-browser-mocks/BUILD.bazel new file mode 100644 index 00000000000000..42c29b72766b94 --- /dev/null +++ b/packages/core/apps/core-apps-browser-mocks/BUILD.bazel @@ -0,0 +1,115 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "core-apps-browser-mocks" +PKG_REQUIRE_NAME = "@kbn/core-apps-browser-mocks" + +SOURCE_FILES = glob( + [ + "**/*.ts", + "**/*.tsx", + ], + exclude = [ + "**/*.config.js", + "**/*.test.*", + "**/*.stories.*", + "**/__snapshots__/**", + "**/integration_tests/**", + "**/mocks/**", + "**/scripts/**", + "**/storybook/**", + "**/test_fixtures/**", + "**/test_helpers/**", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +RUNTIME_DEPS = [ + "@npm//react" +] + +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "//packages/kbn-utility-types:npm_module_types", + "//packages/core/apps/core-apps-browser-internal:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + declaration_map = True, + emit_declaration_only = True, + out_dir = "target_types", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/core/apps/core-apps-browser-mocks/README.md b/packages/core/apps/core-apps-browser-mocks/README.md new file mode 100644 index 00000000000000..5ae368e814c435 --- /dev/null +++ b/packages/core/apps/core-apps-browser-mocks/README.md @@ -0,0 +1,4 @@ +# @kbn/core-apps-browser-mocks + +This package contains mocks for Core's browser-side `coreApps` service. +- `coreAppsMock` diff --git a/src/core/public/core_app/index.ts b/packages/core/apps/core-apps-browser-mocks/index.ts similarity index 81% rename from src/core/public/core_app/index.ts rename to packages/core/apps/core-apps-browser-mocks/index.ts index 594f9975d29fb0..68289764ac3e8a 100644 --- a/src/core/public/core_app/index.ts +++ b/packages/core/apps/core-apps-browser-mocks/index.ts @@ -6,5 +6,4 @@ * Side Public License, v 1. */ -export { CoreApp } from './core_app'; -export { URL_MAX_LENGTH } from './errors'; +export { coreAppsMock } from './src'; diff --git a/packages/core/apps/core-apps-browser-mocks/jest.config.js b/packages/core/apps/core-apps-browser-mocks/jest.config.js new file mode 100644 index 00000000000000..f797f04d42061c --- /dev/null +++ b/packages/core/apps/core-apps-browser-mocks/jest.config.js @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../..', + roots: ['/packages/core/apps/core-apps-browser-mocks'], +}; diff --git a/packages/core/apps/core-apps-browser-mocks/kibana.jsonc b/packages/core/apps/core-apps-browser-mocks/kibana.jsonc new file mode 100644 index 00000000000000..074993f2bd62b1 --- /dev/null +++ b/packages/core/apps/core-apps-browser-mocks/kibana.jsonc @@ -0,0 +1,7 @@ +{ + "type": "shared-common", + "id": "@kbn/core-apps-browser-mocks", + "owner": "@elastic/kibana-core", + "runtimeDeps": [], + "typeDeps": [] +} diff --git a/packages/core/apps/core-apps-browser-mocks/package.json b/packages/core/apps/core-apps-browser-mocks/package.json new file mode 100644 index 00000000000000..486f6445a8b248 --- /dev/null +++ b/packages/core/apps/core-apps-browser-mocks/package.json @@ -0,0 +1,9 @@ +{ + "name": "@kbn/core-apps-browser-mocks", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "browser": "./target_web/index.js", + "author": "Kibana Core", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/src/core/public/core_app/core_app.mock.ts b/packages/core/apps/core-apps-browser-mocks/src/core_app.mock.ts similarity index 77% rename from src/core/public/core_app/core_app.mock.ts rename to packages/core/apps/core-apps-browser-mocks/src/core_app.mock.ts index 04a4eefa0d25f3..fb5a3b54ad5916 100644 --- a/src/core/public/core_app/core_app.mock.ts +++ b/packages/core/apps/core-apps-browser-mocks/src/core_app.mock.ts @@ -7,15 +7,16 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import { CoreApp } from './core_app'; +import type { CoreAppsService } from '@kbn/core-apps-browser-internal'; + +type CoreAppContract = PublicMethodsOf; -type CoreAppContract = PublicMethodsOf; const createMock = (): jest.Mocked => ({ setup: jest.fn(), start: jest.fn(), stop: jest.fn(), }); -export const coreAppMock = { +export const coreAppsMock = { create: createMock, }; diff --git a/packages/core/apps/core-apps-browser-mocks/src/index.ts b/packages/core/apps/core-apps-browser-mocks/src/index.ts new file mode 100644 index 00000000000000..7afedc3d90fcf2 --- /dev/null +++ b/packages/core/apps/core-apps-browser-mocks/src/index.ts @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { coreAppsMock } from './core_app.mock'; diff --git a/packages/core/apps/core-apps-browser-mocks/tsconfig.json b/packages/core/apps/core-apps-browser-mocks/tsconfig.json new file mode 100644 index 00000000000000..26b4c7aca3a676 --- /dev/null +++ b/packages/core/apps/core-apps-browser-mocks/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx", + ] +} diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7dark.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7dark.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7dark.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7dark.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7light.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7light.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7light.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7light.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8dark.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8dark.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8dark.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8dark.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8light.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8light.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8light.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8light.scss diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index e7f9e7d3c3b81e..fdd36c76f6e4d9 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -164,8 +164,8 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/_other_styles.scss, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/styles.scss, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/lib.ts, - /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v8dark.scss, - /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v8light.scss, + /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/styles/core_app/_globals_v8dark.scss, + /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/styles/core_app/_globals_v8light.scss, /packages/kbn-optimizer/src/worker/entry_point_creator.ts, ] `); diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 1b87498496b243..04074fb2b10b40 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -188,7 +188,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: loaderContext, Path.resolve( worker.repoRoot, - `src/core/public/core_app/styles/_globals_${theme}.scss` + `src/core/public/styles/core_app/_globals_${theme}.scss` ) )};\n${content}`; }, @@ -246,7 +246,10 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: extensions: ['.js', '.ts', '.tsx', '.json'], mainFields: ['browser', 'main'], alias: { - core_app_image_assets: Path.resolve(worker.repoRoot, 'src/core/public/core_app/images'), + core_app_image_assets: Path.resolve( + worker.repoRoot, + 'src/core/public/styles/core_app/images' + ), vega: Path.resolve(worker.repoRoot, 'node_modules/vega/build-es5/vega.js'), }, symlinks: false, diff --git a/src/core/public/core_system.test.mocks.ts b/src/core/public/core_system.test.mocks.ts index 2b378b02554cb0..f5b0c017dcd188 100644 --- a/src/core/public/core_system.test.mocks.ts +++ b/src/core/public/core_system.test.mocks.ts @@ -21,7 +21,7 @@ import { pluginsServiceMock } from './plugins/plugins_service.mock'; import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { renderingServiceMock } from '@kbn/core-rendering-browser-mocks'; import { integrationsServiceMock } from '@kbn/core-integrations-browser-mocks'; -import { coreAppMock } from './core_app/core_app.mock'; +import { coreAppsMock } from '@kbn/core-apps-browser-mocks'; export const analyticsServiceStartMock = analyticsServiceMock.createAnalyticsServiceStart(); export const MockAnalyticsService = analyticsServiceMock.create(); @@ -126,10 +126,10 @@ jest.doMock('@kbn/core-integrations-browser-internal', () => ({ IntegrationsService: IntegrationsServiceConstructor, })); -export const MockCoreApp = coreAppMock.create(); +export const MockCoreApp = coreAppsMock.create(); export const CoreAppConstructor = jest.fn().mockImplementation(() => MockCoreApp); -jest.doMock('./core_app', () => ({ - CoreApp: CoreAppConstructor, +jest.doMock('@kbn/core-apps-browser-internal', () => ({ + CoreAppsService: CoreAppConstructor, })); export const MockThemeService = themeServiceMock.create(); diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index cf3a9e6405f690..47ea6dd2ec164f 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -38,10 +38,10 @@ import { type InternalApplicationStart, } from '@kbn/core-application-browser-internal'; import { RenderingService } from '@kbn/core-rendering-browser-internal'; +import { CoreAppsService } from '@kbn/core-apps-browser-internal'; import { fetchOptionalMemoryInfo } from './fetch_optional_memory_info'; import { CoreSetup, CoreStart } from '.'; import { PluginsService } from './plugins'; -import { CoreApp } from './core_app'; import { LOAD_SETUP_DONE, @@ -95,7 +95,7 @@ export class CoreSystem { private readonly docLinks: DocLinksService; private readonly rendering: RenderingService; private readonly integrations: IntegrationsService; - private readonly coreApp: CoreApp; + private readonly coreApp: CoreAppsService; private readonly deprecations: DeprecationsService; private readonly theme: ThemeService; private readonly rootDomElement: HTMLElement; @@ -140,7 +140,7 @@ export class CoreSystem { this.executionContext = new ExecutionContextService(); this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins); - this.coreApp = new CoreApp(this.coreContext); + this.coreApp = new CoreAppsService(this.coreContext); performance.mark(KBN_LOAD_MARKS, { detail: LOAD_CORE_CREATED, diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 9eba054ab53020..e5c137a6d5db4b 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -224,7 +224,7 @@ export type { export type { MountPoint, UnmountCallback, OverlayRef } from '@kbn/core-mount-utils-browser'; -export { URL_MAX_LENGTH } from './core_app'; +export { URL_MAX_LENGTH } from '@kbn/core-apps-browser-internal'; export type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; diff --git a/src/core/public/styles/core_app/README.txt b/src/core/public/styles/core_app/README.txt new file mode 100644 index 00000000000000..06f79f0f1afc1e --- /dev/null +++ b/src/core/public/styles/core_app/README.txt @@ -0,0 +1 @@ +These files are only used by the sass loader, located here: `packages/kbn-optimizer/src/worker/webpack.config.ts` diff --git a/src/core/public/core_app/styles/_globals_v8dark.scss b/src/core/public/styles/core_app/_globals_v8dark.scss similarity index 100% rename from src/core/public/core_app/styles/_globals_v8dark.scss rename to src/core/public/styles/core_app/_globals_v8dark.scss diff --git a/src/core/public/core_app/styles/_globals_v8light.scss b/src/core/public/styles/core_app/_globals_v8light.scss similarity index 100% rename from src/core/public/core_app/styles/_globals_v8light.scss rename to src/core/public/styles/core_app/_globals_v8light.scss diff --git a/src/core/public/core_app/styles/_mixins.scss b/src/core/public/styles/core_app/_mixins.scss similarity index 100% rename from src/core/public/core_app/styles/_mixins.scss rename to src/core/public/styles/core_app/_mixins.scss diff --git a/src/core/public/core_app/images/bg_bottom_branded.svg b/src/core/public/styles/core_app/images/bg_bottom_branded.svg similarity index 100% rename from src/core/public/core_app/images/bg_bottom_branded.svg rename to src/core/public/styles/core_app/images/bg_bottom_branded.svg diff --git a/src/core/public/core_app/images/bg_bottom_branded_dark.svg b/src/core/public/styles/core_app/images/bg_bottom_branded_dark.svg similarity index 100% rename from src/core/public/core_app/images/bg_bottom_branded_dark.svg rename to src/core/public/styles/core_app/images/bg_bottom_branded_dark.svg diff --git a/src/core/public/core_app/images/bg_top_branded.svg b/src/core/public/styles/core_app/images/bg_top_branded.svg similarity index 100% rename from src/core/public/core_app/images/bg_top_branded.svg rename to src/core/public/styles/core_app/images/bg_top_branded.svg diff --git a/src/core/public/core_app/images/bg_top_branded_dark.svg b/src/core/public/styles/core_app/images/bg_top_branded_dark.svg similarity index 100% rename from src/core/public/core_app/images/bg_top_branded_dark.svg rename to src/core/public/styles/core_app/images/bg_top_branded_dark.svg diff --git a/yarn.lock b/yarn.lock index ca0826165cf2ad..31c3399f9a387b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2744,6 +2744,14 @@ version "0.0.0" uid "" +"@kbn/core-apps-browser-internal@link:bazel-bin/packages/core/apps/core-apps-browser-internal": + version "0.0.0" + uid "" + +"@kbn/core-apps-browser-mocks@link:bazel-bin/packages/core/apps/core-apps-browser-mocks": + version "0.0.0" + uid "" + "@kbn/core-base-browser-internal@link:bazel-bin/packages/core/base/core-base-browser-internal": version "0.0.0" uid "" @@ -6727,6 +6735,14 @@ version "0.0.0" uid "" +"@types/kbn__core-apps-browser-internal@link:bazel-bin/packages/core/apps/core-apps-browser-internal/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__core-apps-browser-mocks@link:bazel-bin/packages/core/apps/core-apps-browser-mocks/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__core-base-browser-internal@link:bazel-bin/packages/core/base/core-base-browser-internal/npm_module_types": version "0.0.0" uid "" From 286d54263559a6406724a884ee9bc94b2b9ec111 Mon Sep 17 00:00:00 2001 From: doakalexi <109488926+doakalexi@users.noreply.github.com> Date: Tue, 13 Sep 2022 14:56:08 -0400 Subject: [PATCH 133/144] [ResponseOps][Alerting] Store rule name in alerting event log documents (#140441) * Removing secondary query * Adding field to agg * Removing log statement * Fixing types * Adding rule name to function tests --- .../alerting/common/execution_log_types.ts | 1 + .../lib/get_execution_log_aggregation.test.ts | 27 +++++++++++++------ .../lib/get_execution_log_aggregation.ts | 4 +++ .../routes/get_global_execution_logs.test.ts | 2 ++ .../routes/get_rule_execution_log.test.ts | 2 ++ .../server/rules_client/rules_client.ts | 27 +------------------ .../tests/get_execution_log.test.ts | 5 +++- .../tests/alerting/get_execution_log.ts | 4 +++ 8 files changed, 37 insertions(+), 35 deletions(-) diff --git a/x-pack/plugins/alerting/common/execution_log_types.ts b/x-pack/plugins/alerting/common/execution_log_types.ts index 41406bb6c9dc1e..1938d8be4acd35 100644 --- a/x-pack/plugins/alerting/common/execution_log_types.ts +++ b/x-pack/plugins/alerting/common/execution_log_types.ts @@ -49,6 +49,7 @@ export interface IExecutionLog { schedule_delay_ms: number; timed_out: boolean; rule_id: string; + rule_name: string; } export interface IExecutionErrors { diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts index bd3fc05c6d8f75..e48483785490a6 100644 --- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts +++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.test.ts @@ -278,6 +278,7 @@ describe('getExecutionLogAggregation', () => { 'error.message', 'kibana.version', 'rule.id', + 'rule.name', ], }, }, @@ -482,6 +483,7 @@ describe('getExecutionLogAggregation', () => { 'error.message', 'kibana.version', 'rule.id', + 'rule.name', ], }, }, @@ -686,6 +688,7 @@ describe('getExecutionLogAggregation', () => { 'error.message', 'kibana.version', 'rule.id', + 'rule.name', ], }, }, @@ -776,7 +779,7 @@ describe('formatExecutionLogResult', () => { _id: 'S4wIZX8B8TGQpG7XQZns', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'success', }, @@ -860,7 +863,7 @@ describe('formatExecutionLogResult', () => { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'success', @@ -940,6 +943,7 @@ describe('formatExecutionLogResult', () => { timed_out: false, schedule_delay_ms: 3074, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -961,6 +965,7 @@ describe('formatExecutionLogResult', () => { timed_out: false, schedule_delay_ms: 3126, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, ], }); @@ -1015,7 +1020,7 @@ describe('formatExecutionLogResult', () => { _id: 'S4wIZX8B8TGQpG7XQZns', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'failure', }, @@ -1102,7 +1107,7 @@ describe('formatExecutionLogResult', () => { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'success', }, @@ -1181,6 +1186,7 @@ describe('formatExecutionLogResult', () => { timed_out: false, schedule_delay_ms: 3074, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -1202,6 +1208,7 @@ describe('formatExecutionLogResult', () => { timed_out: false, schedule_delay_ms: 3126, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, ], }); @@ -1256,7 +1263,7 @@ describe('formatExecutionLogResult', () => { _id: 'dJkWa38B1ylB1EvsAckB', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'success', }, @@ -1335,7 +1342,7 @@ describe('formatExecutionLogResult', () => { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'success', }, @@ -1414,6 +1421,7 @@ describe('formatExecutionLogResult', () => { timed_out: true, schedule_delay_ms: 3074, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -1435,6 +1443,7 @@ describe('formatExecutionLogResult', () => { timed_out: false, schedule_delay_ms: 3126, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, ], }); @@ -1489,7 +1498,7 @@ describe('formatExecutionLogResult', () => { _id: '7xKcb38BcntAq5ycFwiu', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'success', }, @@ -1573,7 +1582,7 @@ describe('formatExecutionLogResult', () => { _id: 'zRKbb38BcntAq5ycOwgk', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule_name' }, event: { outcome: 'success', }, @@ -1652,6 +1661,7 @@ describe('formatExecutionLogResult', () => { timed_out: false, schedule_delay_ms: 3126, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, { id: '61bb867b-661a-471f-bf92-23471afa10b3', @@ -1673,6 +1683,7 @@ describe('formatExecutionLogResult', () => { timed_out: false, schedule_delay_ms: 3133, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, ], }); diff --git a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts index 14d67807a86af4..0854488d5f29ee 100644 --- a/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts +++ b/x-pack/plugins/alerting/server/lib/get_execution_log_aggregation.ts @@ -17,6 +17,7 @@ import { IExecutionLog, IExecutionLogResult } from '../../common'; const DEFAULT_MAX_BUCKETS_LIMIT = 1000; // do not retrieve more than this number of executions const RULE_ID_FIELD = 'rule.id'; +const RULE_NAME_FIELD = 'rule.name'; const PROVIDER_FIELD = 'event.provider'; const START_FIELD = 'event.start'; const ACTION_FIELD = 'event.action'; @@ -265,6 +266,7 @@ export function getExecutionLogAggregation({ ERROR_MESSAGE_FIELD, VERSION_FIELD, RULE_ID_FIELD, + RULE_NAME_FIELD, ], }, }, @@ -336,6 +338,7 @@ function formatExecutionLogAggBucket(bucket: IExecutionUuidAggBucket): IExecutio const version = outcomeAndMessage ? outcomeAndMessage?.kibana?.version ?? '' : ''; const ruleId = outcomeAndMessage ? outcomeAndMessage?.rule?.id ?? '' : ''; + const ruleName = outcomeAndMessage ? outcomeAndMessage?.rule?.name ?? '' : ''; return { id: bucket?.key ?? '', timestamp: bucket?.ruleExecution?.executeStartTime.value_as_string ?? '', @@ -355,6 +358,7 @@ function formatExecutionLogAggBucket(bucket: IExecutionUuidAggBucket): IExecutio schedule_delay_ms: scheduleDelayUs / Millis2Nanos, timed_out: timedOut, rule_id: ruleId, + rule_name: ruleName, }; } diff --git a/x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts index 4c7f6c0a2750e0..43b08ed0787e29 100644 --- a/x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_global_execution_logs.test.ts @@ -46,6 +46,7 @@ describe('getRuleExecutionLogRoute', () => { timed_out: false, schedule_delay_ms: 3126, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule-name', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -67,6 +68,7 @@ describe('getRuleExecutionLogRoute', () => { timed_out: false, schedule_delay_ms: 3008, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule-name', }, ], }; diff --git a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts index 9c1be8628c8234..048da6cbabeb35 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_execution_log.test.ts @@ -47,6 +47,7 @@ describe('getRuleExecutionLogRoute', () => { timed_out: false, schedule_delay_ms: 3126, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -68,6 +69,7 @@ describe('getRuleExecutionLogRoute', () => { timed_out: false, schedule_delay_ms: 3008, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule_name', }, ], }; diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index 7d0f6463a48721..55f9ce0da063c1 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -944,32 +944,7 @@ export class RulesClient { } ); - const formattedResult = formatExecutionLogResult(aggResult); - const ruleIds = [...new Set(formattedResult.data.map((l) => l.rule_id))].filter( - Boolean - ) as string[]; - const ruleNameIdEntries = await Promise.all( - ruleIds.map(async (id) => { - try { - const result = await this.get({ id }); - return [id, result.name]; - } catch (e) { - return [id, id]; - } - }) - ); - const ruleNameIdMap: Record = ruleNameIdEntries.reduce( - (result, [key, val]) => ({ ...result, [key]: val }), - {} - ); - - return { - ...formattedResult, - data: formattedResult.data.map((entry) => ({ - ...entry, - rule_name: ruleNameIdMap[entry.rule_id!], - })), - }; + return formatExecutionLogResult(aggResult); } catch (err) { this.logger.debug( `rulesClient.getGlobalExecutionLogWithAuth(): error searching global event log: ${err.message}` diff --git a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts index cf525f59e9448c..f5525820da6dc1 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/get_execution_log.test.ts @@ -145,6 +145,7 @@ const aggregateResults = { _source: { rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + name: 'rule-name', }, event: { outcome: 'success', @@ -248,7 +249,7 @@ const aggregateResults = { _id: 'a4wIZX8B8TGQpG7Xwpnz', _score: 1.0, _source: { - rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef' }, + rule: { id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', name: 'rule-name' }, event: { outcome: 'success', }, @@ -377,6 +378,7 @@ describe('getExecutionLogForRule()', () => { timed_out: false, schedule_delay_ms: 3126, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule-name', }, { id: '41b2755e-765a-4044-9745-b03875d5e79a', @@ -398,6 +400,7 @@ describe('getExecutionLogForRule()', () => { timed_out: false, schedule_delay_ms: 3345, rule_id: 'a348a740-9e2c-11ec-bd64-774ed95c43ef', + rule_name: 'rule-name', }, ], }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_execution_log.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_execution_log.ts index 1f33f44a20d6a0..984b6bbb832f91 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_execution_log.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_execution_log.ts @@ -74,6 +74,7 @@ export default function createGetExecutionLogTests({ getService }: FtrProviderCo let previousTimestamp: string | null = null; for (const log of execLogs) { + expect(log.rule_name).to.equal('abc'); if (previousTimestamp) { // default sort is `desc` by timestamp expect(Date.parse(log.timestamp)).to.be.lessThan(Date.parse(previousTimestamp)); @@ -177,6 +178,7 @@ export default function createGetExecutionLogTests({ getService }: FtrProviderCo expect(execLogs.length).to.eql(1); for (const log of execLogs) { + expect(log.rule_name).to.equal('abc'); expect(log.duration_ms).to.be.greaterThan(0); expect(log.schedule_delay_ms).to.be.greaterThan(0); expect(log.status).to.equal('success'); @@ -314,6 +316,7 @@ export default function createGetExecutionLogTests({ getService }: FtrProviderCo expect(execLogs.length).to.eql(1); for (const log of execLogs) { + expect(log.rule_name).to.equal('abc'); expect(log.status).to.equal('success'); expect(log.num_active_alerts).to.equal(1); @@ -372,6 +375,7 @@ export default function createGetExecutionLogTests({ getService }: FtrProviderCo expect(execLogs.length).to.eql(1); for (const log of execLogs) { + expect(log.rule_name).to.equal('abc'); expect(log.status).to.equal('success'); expect(log.num_active_alerts).to.equal(1); From d2844f7cdae7e0693e652df62b51233201e093f8 Mon Sep 17 00:00:00 2001 From: Baturalp Gurdin <9674241+suchcodemuchwow@users.noreply.github.com> Date: Tue, 13 Sep 2022 22:20:11 +0300 Subject: [PATCH 134/144] Revert "Migrate client-side `coreApp` domain to packages" (#140653) This reverts commit 4c6dc3c86d60dc69ce9e9c6e780bdb0b6fa2c9a2. --- .github/CODEOWNERS | 2 - package.json | 4 - packages/BUILD.bazel | 4 - .../core-apps-browser-internal/BUILD.bazel | 137 ------------------ .../apps/core-apps-browser-internal/README.md | 3 - .../apps/core-apps-browser-internal/index.ts | 10 -- .../core-apps-browser-internal/jest.config.js | 13 -- .../core-apps-browser-internal/kibana.jsonc | 7 - .../core-apps-browser-internal/package.json | 9 -- .../core-apps-browser-internal/src/index.ts | 11 -- .../core-apps-browser-internal/tsconfig.json | 19 --- .../apps/core-apps-browser-mocks/BUILD.bazel | 115 --------------- .../apps/core-apps-browser-mocks/README.md | 4 - .../core-apps-browser-mocks/jest.config.js | 13 -- .../apps/core-apps-browser-mocks/kibana.jsonc | 7 - .../apps/core-apps-browser-mocks/package.json | 9 -- .../apps/core-apps-browser-mocks/src/index.ts | 9 -- .../core-apps-browser-mocks/tsconfig.json | 18 --- .../styles}/_globals_v7dark.scss | 0 .../styles}/_globals_v7light.scss | 0 .../styles}/_globals_v8dark.scss | 0 .../styles}/_globals_v8light.scss | 0 .../basic_optimization.test.ts | 4 +- .../src/worker/webpack.config.ts | 7 +- .../core/public/core_app}/core_app.mock.ts | 7 +- .../core/public/core_app}/core_app.ts | 16 +- .../errors/error_application.test.ts | 0 .../core_app}/errors/error_application.tsx | 0 .../core/public/core_app}/errors/index.ts | 0 .../core_app}/errors/public_base_url.test.tsx | 0 .../core_app}/errors/public_base_url.tsx | 3 +- .../core_app}/errors/url_overflow.test.ts | 0 .../public/core_app}/errors/url_overflow.tsx | 0 .../core_app}/errors/url_overflow_ui.tsx | 0 .../core_app/images/bg_bottom_branded.svg | 0 .../images/bg_bottom_branded_dark.svg | 0 .../core_app/images/bg_top_branded.svg | 0 .../core_app/images/bg_top_branded_dark.svg | 0 .../core/public/core_app}/index.ts | 3 +- .../__snapshots__/metric_tiles.test.tsx.snap | 0 .../__snapshots__/server_status.test.tsx.snap | 0 .../__snapshots__/status_table.test.tsx.snap | 0 .../core_app}/status/components/index.ts | 0 .../status/components/metric_tiles.test.tsx | 0 .../status/components/metric_tiles.tsx | 0 .../status/components/server_status.test.tsx | 0 .../status/components/server_status.tsx | 0 .../status/components/status_badge.test.tsx | 0 .../status/components/status_badge.tsx | 0 .../status/components/status_expanded_row.tsx | 0 .../status/components/status_section.tsx | 0 .../status/components/status_table.test.tsx | 0 .../status/components/status_table.tsx | 0 .../status/components/version_header.test.tsx | 0 .../status/components/version_header.tsx | 0 .../core/public/core_app}/status/index.ts | 0 .../status/lib/format_number.test.ts | 0 .../core_app}/status/lib/format_number.ts | 0 .../core/public/core_app}/status/lib/index.ts | 0 .../core_app}/status/lib/load_status.test.ts | 0 .../core_app}/status/lib/load_status.ts | 2 +- .../core_app}/status/lib/status_level.test.ts | 0 .../core_app}/status/lib/status_level.ts | 0 .../public/core_app}/status/render_app.tsx | 0 .../public/core_app}/status/status_app.tsx | 0 .../styles}/_globals_v8dark.scss | 0 .../styles}/_globals_v8light.scss | 0 .../core_app => core_app/styles}/_mixins.scss | 0 src/core/public/core_system.test.mocks.ts | 8 +- src/core/public/core_system.ts | 6 +- src/core/public/index.ts | 2 +- src/core/public/styles/core_app/README.txt | 1 - yarn.lock | 16 -- 73 files changed, 24 insertions(+), 445 deletions(-) delete mode 100644 packages/core/apps/core-apps-browser-internal/BUILD.bazel delete mode 100644 packages/core/apps/core-apps-browser-internal/README.md delete mode 100644 packages/core/apps/core-apps-browser-internal/index.ts delete mode 100644 packages/core/apps/core-apps-browser-internal/jest.config.js delete mode 100644 packages/core/apps/core-apps-browser-internal/kibana.jsonc delete mode 100644 packages/core/apps/core-apps-browser-internal/package.json delete mode 100644 packages/core/apps/core-apps-browser-internal/src/index.ts delete mode 100644 packages/core/apps/core-apps-browser-internal/tsconfig.json delete mode 100644 packages/core/apps/core-apps-browser-mocks/BUILD.bazel delete mode 100644 packages/core/apps/core-apps-browser-mocks/README.md delete mode 100644 packages/core/apps/core-apps-browser-mocks/jest.config.js delete mode 100644 packages/core/apps/core-apps-browser-mocks/kibana.jsonc delete mode 100644 packages/core/apps/core-apps-browser-mocks/package.json delete mode 100644 packages/core/apps/core-apps-browser-mocks/src/index.ts delete mode 100644 packages/core/apps/core-apps-browser-mocks/tsconfig.json rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{styles/core_app => core_app/styles}/_globals_v7dark.scss (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{styles/core_app => core_app/styles}/_globals_v7light.scss (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{styles/core_app => core_app/styles}/_globals_v8dark.scss (100%) rename packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/{styles/core_app => core_app/styles}/_globals_v8light.scss (100%) rename {packages/core/apps/core-apps-browser-mocks/src => src/core/public/core_app}/core_app.mock.ts (77%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/core_app.ts (91%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/error_application.test.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/error_application.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/index.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/public_base_url.test.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/public_base_url.tsx (95%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/url_overflow.test.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/url_overflow.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/errors/url_overflow_ui.tsx (100%) rename src/core/public/{styles => }/core_app/images/bg_bottom_branded.svg (100%) rename src/core/public/{styles => }/core_app/images/bg_bottom_branded_dark.svg (100%) rename src/core/public/{styles => }/core_app/images/bg_top_branded.svg (100%) rename src/core/public/{styles => }/core_app/images/bg_top_branded_dark.svg (100%) rename {packages/core/apps/core-apps-browser-mocks => src/core/public/core_app}/index.ts (81%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/__snapshots__/metric_tiles.test.tsx.snap (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/__snapshots__/server_status.test.tsx.snap (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/__snapshots__/status_table.test.tsx.snap (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/index.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/metric_tiles.test.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/metric_tiles.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/server_status.test.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/server_status.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/status_badge.test.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/status_badge.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/status_expanded_row.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/status_section.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/status_table.test.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/status_table.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/version_header.test.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/components/version_header.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/index.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/lib/format_number.test.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/lib/format_number.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/lib/index.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/lib/load_status.test.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/lib/load_status.ts (99%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/lib/status_level.test.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/lib/status_level.ts (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/render_app.tsx (100%) rename {packages/core/apps/core-apps-browser-internal/src => src/core/public/core_app}/status/status_app.tsx (100%) rename src/core/public/{styles/core_app => core_app/styles}/_globals_v8dark.scss (100%) rename src/core/public/{styles/core_app => core_app/styles}/_globals_v8light.scss (100%) rename src/core/public/{styles/core_app => core_app/styles}/_mixins.scss (100%) delete mode 100644 src/core/public/styles/core_app/README.txt diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index dbc10f3a6c41e2..89f74e669e9cf3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -658,8 +658,6 @@ packages/core/application/core-application-browser @elastic/kibana-core packages/core/application/core-application-browser-internal @elastic/kibana-core packages/core/application/core-application-browser-mocks @elastic/kibana-core packages/core/application/core-application-common @elastic/kibana-core -packages/core/apps/core-apps-browser-internal @elastic/kibana-core -packages/core/apps/core-apps-browser-mocks @elastic/kibana-core packages/core/base/core-base-browser-internal @elastic/kibana-core packages/core/base/core-base-browser-mocks @elastic/kibana-core packages/core/base/core-base-common @elastic/kibana-core diff --git a/package.json b/package.json index 4fa23bdb9ef47f..c8c1aa501b9814 100644 --- a/package.json +++ b/package.json @@ -156,8 +156,6 @@ "@kbn/core-application-browser-internal": "link:bazel-bin/packages/core/application/core-application-browser-internal", "@kbn/core-application-browser-mocks": "link:bazel-bin/packages/core/application/core-application-browser-mocks", "@kbn/core-application-common": "link:bazel-bin/packages/core/application/core-application-common", - "@kbn/core-apps-browser-internal": "link:bazel-bin/packages/core/apps/core-apps-browser-internal", - "@kbn/core-apps-browser-mocks": "link:bazel-bin/packages/core/apps/core-apps-browser-mocks", "@kbn/core-base-browser-internal": "link:bazel-bin/packages/core/base/core-base-browser-internal", "@kbn/core-base-browser-mocks": "link:bazel-bin/packages/core/base/core-base-browser-mocks", "@kbn/core-base-common": "link:bazel-bin/packages/core/base/core-base-common", @@ -846,8 +844,6 @@ "@types/kbn__core-application-browser-internal": "link:bazel-bin/packages/core/application/core-application-browser-internal/npm_module_types", "@types/kbn__core-application-browser-mocks": "link:bazel-bin/packages/core/application/core-application-browser-mocks/npm_module_types", "@types/kbn__core-application-common": "link:bazel-bin/packages/core/application/core-application-common/npm_module_types", - "@types/kbn__core-apps-browser-internal": "link:bazel-bin/packages/core/apps/core-apps-browser-internal/npm_module_types", - "@types/kbn__core-apps-browser-mocks": "link:bazel-bin/packages/core/apps/core-apps-browser-mocks/npm_module_types", "@types/kbn__core-base-browser": "link:bazel-bin/packages/core/base/core-base-browser/npm_module_types", "@types/kbn__core-base-browser-internal": "link:bazel-bin/packages/core/base/core-base-browser-internal/npm_module_types", "@types/kbn__core-base-browser-mocks": "link:bazel-bin/packages/core/base/core-base-browser-mocks/npm_module_types", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index 18c2202fb8d2cd..b898faee5fb07e 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -24,8 +24,6 @@ filegroup( "//packages/core/application/core-application-browser-internal:build", "//packages/core/application/core-application-browser-mocks:build", "//packages/core/application/core-application-common:build", - "//packages/core/apps/core-apps-browser-internal:build", - "//packages/core/apps/core-apps-browser-mocks:build", "//packages/core/base/core-base-browser-internal:build", "//packages/core/base/core-base-browser-mocks:build", "//packages/core/base/core-base-common:build", @@ -334,8 +332,6 @@ filegroup( "//packages/core/application/core-application-browser-internal:build_types", "//packages/core/application/core-application-browser-mocks:build_types", "//packages/core/application/core-application-common:build_types", - "//packages/core/apps/core-apps-browser-internal:build_types", - "//packages/core/apps/core-apps-browser-mocks:build_types", "//packages/core/base/core-base-browser-internal:build_types", "//packages/core/base/core-base-browser-mocks:build_types", "//packages/core/base/core-base-common:build_types", diff --git a/packages/core/apps/core-apps-browser-internal/BUILD.bazel b/packages/core/apps/core-apps-browser-internal/BUILD.bazel deleted file mode 100644 index 4ca5c1a1cf2af1..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/BUILD.bazel +++ /dev/null @@ -1,137 +0,0 @@ -load("@npm//@bazel/typescript:index.bzl", "ts_config") -load("@build_bazel_rules_nodejs//:index.bzl", "js_library") -load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") - -PKG_DIRNAME = "core-apps-browser-internal" -PKG_REQUIRE_NAME = "@kbn/core-apps-browser-internal" - -SOURCE_FILES = glob( - [ - "**/*.ts", - "**/*.tsx", - ], - exclude = [ - "**/*.config.js", - "**/*.mock.*", - "**/*.test.*", - "**/*.stories.*", - "**/__snapshots__/**", - "**/integration_tests/**", - "**/mocks/**", - "**/scripts/**", - "**/storybook/**", - "**/test_fixtures/**", - "**/test_helpers/**", - ], -) - -SRCS = SOURCE_FILES - -filegroup( - name = "srcs", - srcs = SRCS, -) - -NPM_MODULE_EXTRA_FILES = [ - "package.json", -] - -RUNTIME_DEPS = [ - "@npm//react", - "@npm//react-dom", - "@npm//history", - "@npm//@elastic/eui", - "//packages/kbn-i18n", - "//packages/kbn-i18n-react", - "//packages/core/mount-utils/core-mount-utils-browser-internal", -] - -TYPES_DEPS = [ - "@npm//@types/node", - "@npm//@types/jest", - "@npm//@types/react", - "@npm//@types/react-dom", - "@npm//@types/history", - "@npm//@elastic/eui", - "//packages/kbn-i18n:npm_module_types", - "//packages/kbn-i18n-react:npm_module_types", - "//packages/core/base/core-base-browser-internal:npm_module_types", - "//packages/core/injected-metadata/core-injected-metadata-browser-internal:npm_module_types", - "//packages/core/doc-links/core-doc-links-browser:npm_module_types", - "//packages/core/http/core-http-browser:npm_module_types", - "//packages/core/ui-settings/core-ui-settings-browser:npm_module_types", - "//packages/core/notifications/core-notifications-browser:npm_module_types", - "//packages/core/application/core-application-browser:npm_module_types", - "//packages/core/application/core-application-browser-internal:npm_module_types", - "//packages/core/theme/core-theme-browser-internal:npm_module_types", - "//packages/core/mount-utils/core-mount-utils-browser-internal:npm_module_types", - "//packages/core/status/core-status-common-internal:npm_module_types", -] - -jsts_transpiler( - name = "target_node", - srcs = SRCS, - build_pkg_name = package_name(), -) - -jsts_transpiler( - name = "target_web", - srcs = SRCS, - build_pkg_name = package_name(), - web = True, -) - -ts_config( - name = "tsconfig", - src = "tsconfig.json", - deps = [ - "//:tsconfig.base.json", - "//:tsconfig.bazel.json", - ], -) - -ts_project( - name = "tsc_types", - args = ['--pretty'], - srcs = SRCS, - deps = TYPES_DEPS, - declaration = True, - declaration_map = True, - emit_declaration_only = True, - out_dir = "target_types", - tsconfig = ":tsconfig", -) - -js_library( - name = PKG_DIRNAME, - srcs = NPM_MODULE_EXTRA_FILES, - deps = RUNTIME_DEPS + [":target_node", ":target_web"], - package_name = PKG_REQUIRE_NAME, - visibility = ["//visibility:public"], -) - -pkg_npm( - name = "npm_module", - deps = [":" + PKG_DIRNAME], -) - -filegroup( - name = "build", - srcs = [":npm_module"], - visibility = ["//visibility:public"], -) - -pkg_npm_types( - name = "npm_module_types", - srcs = SRCS, - deps = [":tsc_types"], - package_name = PKG_REQUIRE_NAME, - tsconfig = ":tsconfig", - visibility = ["//visibility:public"], -) - -filegroup( - name = "build_types", - srcs = [":npm_module_types"], - visibility = ["//visibility:public"], -) diff --git a/packages/core/apps/core-apps-browser-internal/README.md b/packages/core/apps/core-apps-browser-internal/README.md deleted file mode 100644 index 8412844a911df4..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @kbn/core-apps-browser-internal - -This package contains the internal types and implementation of Core's `coreApps` service. diff --git a/packages/core/apps/core-apps-browser-internal/index.ts b/packages/core/apps/core-apps-browser-internal/index.ts deleted file mode 100644 index 35678cd2a19fd4..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/index.ts +++ /dev/null @@ -1,10 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { CoreAppsService, URL_MAX_LENGTH } from './src'; -export type { CoreAppsServiceSetupDeps, CoreAppsServiceStartDeps } from './src'; diff --git a/packages/core/apps/core-apps-browser-internal/jest.config.js b/packages/core/apps/core-apps-browser-internal/jest.config.js deleted file mode 100644 index 80df7f644eab5f..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/jest.config.js +++ /dev/null @@ -1,13 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../../..', - roots: ['/packages/core/apps/core-apps-browser-internal'], -}; diff --git a/packages/core/apps/core-apps-browser-internal/kibana.jsonc b/packages/core/apps/core-apps-browser-internal/kibana.jsonc deleted file mode 100644 index 552de143ce1dec..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/kibana.jsonc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/core-apps-browser-internal", - "owner": "@elastic/kibana-core", - "runtimeDeps": [], - "typeDeps": [] -} diff --git a/packages/core/apps/core-apps-browser-internal/package.json b/packages/core/apps/core-apps-browser-internal/package.json deleted file mode 100644 index 58262f9a7aaeb7..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "@kbn/core-apps-browser-internal", - "private": true, - "version": "1.0.0", - "main": "./target_node/index.js", - "browser": "./target_web/index.js", - "author": "Kibana Core", - "license": "SSPL-1.0 OR Elastic License 2.0" -} diff --git a/packages/core/apps/core-apps-browser-internal/src/index.ts b/packages/core/apps/core-apps-browser-internal/src/index.ts deleted file mode 100644 index d0bb30144b7dbc..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/src/index.ts +++ /dev/null @@ -1,11 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { CoreAppsService } from './core_app'; -export { URL_MAX_LENGTH } from './errors'; -export type { CoreAppsServiceSetupDeps, CoreAppsServiceStartDeps } from './core_app'; diff --git a/packages/core/apps/core-apps-browser-internal/tsconfig.json b/packages/core/apps/core-apps-browser-internal/tsconfig.json deleted file mode 100644 index 2249e2ee937617..00000000000000 --- a/packages/core/apps/core-apps-browser-internal/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "../../../../tsconfig.bazel.json", - "compilerOptions": { - "declaration": true, - "declarationMap": true, - "emitDeclarationOnly": true, - "outDir": "target_types", - "stripInternal": false, - "types": [ - "jest", - "node", - "react" - ] - }, - "include": [ - "**/*.ts", - "**/*.tsx", - ] -} diff --git a/packages/core/apps/core-apps-browser-mocks/BUILD.bazel b/packages/core/apps/core-apps-browser-mocks/BUILD.bazel deleted file mode 100644 index 42c29b72766b94..00000000000000 --- a/packages/core/apps/core-apps-browser-mocks/BUILD.bazel +++ /dev/null @@ -1,115 +0,0 @@ -load("@npm//@bazel/typescript:index.bzl", "ts_config") -load("@build_bazel_rules_nodejs//:index.bzl", "js_library") -load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") - -PKG_DIRNAME = "core-apps-browser-mocks" -PKG_REQUIRE_NAME = "@kbn/core-apps-browser-mocks" - -SOURCE_FILES = glob( - [ - "**/*.ts", - "**/*.tsx", - ], - exclude = [ - "**/*.config.js", - "**/*.test.*", - "**/*.stories.*", - "**/__snapshots__/**", - "**/integration_tests/**", - "**/mocks/**", - "**/scripts/**", - "**/storybook/**", - "**/test_fixtures/**", - "**/test_helpers/**", - ], -) - -SRCS = SOURCE_FILES - -filegroup( - name = "srcs", - srcs = SRCS, -) - -NPM_MODULE_EXTRA_FILES = [ - "package.json", -] - -RUNTIME_DEPS = [ - "@npm//react" -] - -TYPES_DEPS = [ - "@npm//@types/node", - "@npm//@types/jest", - "//packages/kbn-utility-types:npm_module_types", - "//packages/core/apps/core-apps-browser-internal:npm_module_types", -] - -jsts_transpiler( - name = "target_node", - srcs = SRCS, - build_pkg_name = package_name(), -) - -jsts_transpiler( - name = "target_web", - srcs = SRCS, - build_pkg_name = package_name(), - web = True, -) - -ts_config( - name = "tsconfig", - src = "tsconfig.json", - deps = [ - "//:tsconfig.base.json", - "//:tsconfig.bazel.json", - ], -) - -ts_project( - name = "tsc_types", - args = ['--pretty'], - srcs = SRCS, - deps = TYPES_DEPS, - declaration = True, - declaration_map = True, - emit_declaration_only = True, - out_dir = "target_types", - tsconfig = ":tsconfig", -) - -js_library( - name = PKG_DIRNAME, - srcs = NPM_MODULE_EXTRA_FILES, - deps = RUNTIME_DEPS + [":target_node", ":target_web"], - package_name = PKG_REQUIRE_NAME, - visibility = ["//visibility:public"], -) - -pkg_npm( - name = "npm_module", - deps = [":" + PKG_DIRNAME], -) - -filegroup( - name = "build", - srcs = [":npm_module"], - visibility = ["//visibility:public"], -) - -pkg_npm_types( - name = "npm_module_types", - srcs = SRCS, - deps = [":tsc_types"], - package_name = PKG_REQUIRE_NAME, - tsconfig = ":tsconfig", - visibility = ["//visibility:public"], -) - -filegroup( - name = "build_types", - srcs = [":npm_module_types"], - visibility = ["//visibility:public"], -) diff --git a/packages/core/apps/core-apps-browser-mocks/README.md b/packages/core/apps/core-apps-browser-mocks/README.md deleted file mode 100644 index 5ae368e814c435..00000000000000 --- a/packages/core/apps/core-apps-browser-mocks/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# @kbn/core-apps-browser-mocks - -This package contains mocks for Core's browser-side `coreApps` service. -- `coreAppsMock` diff --git a/packages/core/apps/core-apps-browser-mocks/jest.config.js b/packages/core/apps/core-apps-browser-mocks/jest.config.js deleted file mode 100644 index f797f04d42061c..00000000000000 --- a/packages/core/apps/core-apps-browser-mocks/jest.config.js +++ /dev/null @@ -1,13 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../../..', - roots: ['/packages/core/apps/core-apps-browser-mocks'], -}; diff --git a/packages/core/apps/core-apps-browser-mocks/kibana.jsonc b/packages/core/apps/core-apps-browser-mocks/kibana.jsonc deleted file mode 100644 index 074993f2bd62b1..00000000000000 --- a/packages/core/apps/core-apps-browser-mocks/kibana.jsonc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/core-apps-browser-mocks", - "owner": "@elastic/kibana-core", - "runtimeDeps": [], - "typeDeps": [] -} diff --git a/packages/core/apps/core-apps-browser-mocks/package.json b/packages/core/apps/core-apps-browser-mocks/package.json deleted file mode 100644 index 486f6445a8b248..00000000000000 --- a/packages/core/apps/core-apps-browser-mocks/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "@kbn/core-apps-browser-mocks", - "private": true, - "version": "1.0.0", - "main": "./target_node/index.js", - "browser": "./target_web/index.js", - "author": "Kibana Core", - "license": "SSPL-1.0 OR Elastic License 2.0" -} diff --git a/packages/core/apps/core-apps-browser-mocks/src/index.ts b/packages/core/apps/core-apps-browser-mocks/src/index.ts deleted file mode 100644 index 7afedc3d90fcf2..00000000000000 --- a/packages/core/apps/core-apps-browser-mocks/src/index.ts +++ /dev/null @@ -1,9 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { coreAppsMock } from './core_app.mock'; diff --git a/packages/core/apps/core-apps-browser-mocks/tsconfig.json b/packages/core/apps/core-apps-browser-mocks/tsconfig.json deleted file mode 100644 index 26b4c7aca3a676..00000000000000 --- a/packages/core/apps/core-apps-browser-mocks/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "../../../../tsconfig.bazel.json", - "compilerOptions": { - "declaration": true, - "declarationMap": true, - "emitDeclarationOnly": true, - "outDir": "target_types", - "stripInternal": false, - "types": [ - "jest", - "node" - ] - }, - "include": [ - "**/*.ts", - "**/*.tsx", - ] -} diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7dark.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7dark.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7dark.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7dark.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7light.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7light.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v7light.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v7light.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8dark.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8dark.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8dark.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8dark.scss diff --git a/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8light.scss b/packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8light.scss similarity index 100% rename from packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/styles/core_app/_globals_v8light.scss rename to packages/kbn-optimizer/src/__fixtures__/mock_repo/src/core/public/core_app/styles/_globals_v8light.scss diff --git a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts index fdd36c76f6e4d9..e7f9e7d3c3b81e 100644 --- a/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts +++ b/packages/kbn-optimizer/src/integration_tests/basic_optimization.test.ts @@ -164,8 +164,8 @@ it('builds expected bundles, saves bundle counts to metadata', async () => { /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/_other_styles.scss, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/legacy/styles.scss, /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/plugins/bar/public/lib.ts, - /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/styles/core_app/_globals_v8dark.scss, - /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/styles/core_app/_globals_v8light.scss, + /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v8dark.scss, + /packages/kbn-optimizer/src/__fixtures__/__tmp__/mock_repo/src/core/public/core_app/styles/_globals_v8light.scss, /packages/kbn-optimizer/src/worker/entry_point_creator.ts, ] `); diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 04074fb2b10b40..1b87498496b243 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -188,7 +188,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: loaderContext, Path.resolve( worker.repoRoot, - `src/core/public/styles/core_app/_globals_${theme}.scss` + `src/core/public/core_app/styles/_globals_${theme}.scss` ) )};\n${content}`; }, @@ -246,10 +246,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: extensions: ['.js', '.ts', '.tsx', '.json'], mainFields: ['browser', 'main'], alias: { - core_app_image_assets: Path.resolve( - worker.repoRoot, - 'src/core/public/styles/core_app/images' - ), + core_app_image_assets: Path.resolve(worker.repoRoot, 'src/core/public/core_app/images'), vega: Path.resolve(worker.repoRoot, 'node_modules/vega/build-es5/vega.js'), }, symlinks: false, diff --git a/packages/core/apps/core-apps-browser-mocks/src/core_app.mock.ts b/src/core/public/core_app/core_app.mock.ts similarity index 77% rename from packages/core/apps/core-apps-browser-mocks/src/core_app.mock.ts rename to src/core/public/core_app/core_app.mock.ts index fb5a3b54ad5916..04a4eefa0d25f3 100644 --- a/packages/core/apps/core-apps-browser-mocks/src/core_app.mock.ts +++ b/src/core/public/core_app/core_app.mock.ts @@ -7,16 +7,15 @@ */ import type { PublicMethodsOf } from '@kbn/utility-types'; -import type { CoreAppsService } from '@kbn/core-apps-browser-internal'; - -type CoreAppContract = PublicMethodsOf; +import { CoreApp } from './core_app'; +type CoreAppContract = PublicMethodsOf; const createMock = (): jest.Mocked => ({ setup: jest.fn(), start: jest.fn(), stop: jest.fn(), }); -export const coreAppsMock = { +export const coreAppMock = { create: createMock, }; diff --git a/packages/core/apps/core-apps-browser-internal/src/core_app.ts b/src/core/public/core_app/core_app.ts similarity index 91% rename from packages/core/apps/core-apps-browser-internal/src/core_app.ts rename to src/core/public/core_app/core_app.ts index e8a61de40bea2e..7b4fd29011b9bd 100644 --- a/packages/core/apps/core-apps-browser-internal/src/core_app.ts +++ b/src/core/public/core_app/core_app.ts @@ -25,14 +25,14 @@ import { } from './errors'; import { renderApp as renderStatusApp } from './status'; -export interface CoreAppsServiceSetupDeps { +export interface SetupDeps { application: InternalApplicationSetup; http: HttpSetup; injectedMetadata: InternalInjectedMetadataSetup; notifications: NotificationsSetup; } -export interface CoreAppsServiceStartDeps { +export interface StartDeps { application: InternalApplicationStart; docLinks: DocLinksStart; http: HttpStart; @@ -40,12 +40,12 @@ export interface CoreAppsServiceStartDeps { uiSettings: IUiSettingsClient; } -export class CoreAppsService { +export class CoreApp { private stopHistoryListening?: UnregisterCallback; constructor(private readonly coreContext: CoreContext) {} - public setup({ application, http, injectedMetadata, notifications }: CoreAppsServiceSetupDeps) { + public setup({ application, http, injectedMetadata, notifications }: SetupDeps) { application.register(this.coreContext.coreId, { id: 'error', title: 'App Error', @@ -73,13 +73,7 @@ export class CoreAppsService { }); } - public start({ - application, - docLinks, - http, - notifications, - uiSettings, - }: CoreAppsServiceStartDeps) { + public start({ application, docLinks, http, notifications, uiSettings }: StartDeps) { if (!application.history) { return; } diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts b/src/core/public/core_app/errors/error_application.test.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/errors/error_application.test.ts rename to src/core/public/core_app/errors/error_application.test.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/error_application.tsx b/src/core/public/core_app/errors/error_application.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/errors/error_application.tsx rename to src/core/public/core_app/errors/error_application.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/index.ts b/src/core/public/core_app/errors/index.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/errors/index.ts rename to src/core/public/core_app/errors/index.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.test.tsx b/src/core/public/core_app/errors/public_base_url.test.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.test.tsx rename to src/core/public/core_app/errors/public_base_url.test.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx b/src/core/public/core_app/errors/public_base_url.tsx similarity index 95% rename from packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx rename to src/core/public/core_app/errors/public_base_url.tsx index ec5f45930ce228..f86903f3c185fe 100644 --- a/packages/core/apps/core-apps-browser-internal/src/errors/public_base_url.tsx +++ b/src/core/public/core_app/errors/public_base_url.tsx @@ -12,9 +12,8 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { DocLinksStart } from '@kbn/core-doc-links-browser'; -import type { HttpStart } from '@kbn/core-http-browser'; -import type { NotificationsStart } from '@kbn/core-notifications-browser'; import { mountReactNode } from '@kbn/core-mount-utils-browser-internal'; +import type { HttpStart, NotificationsStart } from '../..'; /** Only exported for tests */ export const MISSING_CONFIG_STORAGE_KEY = `core.warnings.publicBaseUrlMissingDismissed`; diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts b/src/core/public/core_app/errors/url_overflow.test.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.test.ts rename to src/core/public/core_app/errors/url_overflow.test.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.tsx b/src/core/public/core_app/errors/url_overflow.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/errors/url_overflow.tsx rename to src/core/public/core_app/errors/url_overflow.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/errors/url_overflow_ui.tsx b/src/core/public/core_app/errors/url_overflow_ui.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/errors/url_overflow_ui.tsx rename to src/core/public/core_app/errors/url_overflow_ui.tsx diff --git a/src/core/public/styles/core_app/images/bg_bottom_branded.svg b/src/core/public/core_app/images/bg_bottom_branded.svg similarity index 100% rename from src/core/public/styles/core_app/images/bg_bottom_branded.svg rename to src/core/public/core_app/images/bg_bottom_branded.svg diff --git a/src/core/public/styles/core_app/images/bg_bottom_branded_dark.svg b/src/core/public/core_app/images/bg_bottom_branded_dark.svg similarity index 100% rename from src/core/public/styles/core_app/images/bg_bottom_branded_dark.svg rename to src/core/public/core_app/images/bg_bottom_branded_dark.svg diff --git a/src/core/public/styles/core_app/images/bg_top_branded.svg b/src/core/public/core_app/images/bg_top_branded.svg similarity index 100% rename from src/core/public/styles/core_app/images/bg_top_branded.svg rename to src/core/public/core_app/images/bg_top_branded.svg diff --git a/src/core/public/styles/core_app/images/bg_top_branded_dark.svg b/src/core/public/core_app/images/bg_top_branded_dark.svg similarity index 100% rename from src/core/public/styles/core_app/images/bg_top_branded_dark.svg rename to src/core/public/core_app/images/bg_top_branded_dark.svg diff --git a/packages/core/apps/core-apps-browser-mocks/index.ts b/src/core/public/core_app/index.ts similarity index 81% rename from packages/core/apps/core-apps-browser-mocks/index.ts rename to src/core/public/core_app/index.ts index 68289764ac3e8a..594f9975d29fb0 100644 --- a/packages/core/apps/core-apps-browser-mocks/index.ts +++ b/src/core/public/core_app/index.ts @@ -6,4 +6,5 @@ * Side Public License, v 1. */ -export { coreAppsMock } from './src'; +export { CoreApp } from './core_app'; +export { URL_MAX_LENGTH } from './errors'; diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/metric_tiles.test.tsx.snap b/src/core/public/core_app/status/components/__snapshots__/metric_tiles.test.tsx.snap similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/metric_tiles.test.tsx.snap rename to src/core/public/core_app/status/components/__snapshots__/metric_tiles.test.tsx.snap diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/server_status.test.tsx.snap b/src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/server_status.test.tsx.snap rename to src/core/public/core_app/status/components/__snapshots__/server_status.test.tsx.snap diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/status_table.test.tsx.snap b/src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/__snapshots__/status_table.test.tsx.snap rename to src/core/public/core_app/status/components/__snapshots__/status_table.test.tsx.snap diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/index.ts b/src/core/public/core_app/status/components/index.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/index.ts rename to src/core/public/core_app/status/components/index.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.test.tsx b/src/core/public/core_app/status/components/metric_tiles.test.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.test.tsx rename to src/core/public/core_app/status/components/metric_tiles.test.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.tsx b/src/core/public/core_app/status/components/metric_tiles.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/metric_tiles.tsx rename to src/core/public/core_app/status/components/metric_tiles.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/server_status.test.tsx b/src/core/public/core_app/status/components/server_status.test.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/server_status.test.tsx rename to src/core/public/core_app/status/components/server_status.test.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/server_status.tsx b/src/core/public/core_app/status/components/server_status.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/server_status.tsx rename to src/core/public/core_app/status/components/server_status.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.test.tsx b/src/core/public/core_app/status/components/status_badge.test.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.test.tsx rename to src/core/public/core_app/status/components/status_badge.test.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.tsx b/src/core/public/core_app/status/components/status_badge.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/status_badge.tsx rename to src/core/public/core_app/status/components/status_badge.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/status_expanded_row.tsx b/src/core/public/core_app/status/components/status_expanded_row.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/status_expanded_row.tsx rename to src/core/public/core_app/status/components/status_expanded_row.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/status_section.tsx b/src/core/public/core_app/status/components/status_section.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/status_section.tsx rename to src/core/public/core_app/status/components/status_section.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/status_table.test.tsx b/src/core/public/core_app/status/components/status_table.test.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/status_table.test.tsx rename to src/core/public/core_app/status/components/status_table.test.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/status_table.tsx b/src/core/public/core_app/status/components/status_table.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/status_table.tsx rename to src/core/public/core_app/status/components/status_table.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/version_header.test.tsx b/src/core/public/core_app/status/components/version_header.test.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/version_header.test.tsx rename to src/core/public/core_app/status/components/version_header.test.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/components/version_header.tsx b/src/core/public/core_app/status/components/version_header.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/components/version_header.tsx rename to src/core/public/core_app/status/components/version_header.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/index.ts b/src/core/public/core_app/status/index.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/index.ts rename to src/core/public/core_app/status/index.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.test.ts b/src/core/public/core_app/status/lib/format_number.test.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.test.ts rename to src/core/public/core_app/status/lib/format_number.test.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.ts b/src/core/public/core_app/status/lib/format_number.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/lib/format_number.ts rename to src/core/public/core_app/status/lib/format_number.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/index.ts b/src/core/public/core_app/status/lib/index.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/lib/index.ts rename to src/core/public/core_app/status/lib/index.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.test.ts b/src/core/public/core_app/status/lib/load_status.test.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.test.ts rename to src/core/public/core_app/status/lib/load_status.test.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts b/src/core/public/core_app/status/lib/load_status.ts similarity index 99% rename from packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts rename to src/core/public/core_app/status/lib/load_status.ts index c3ebd9923e2a81..5a4b2b5907ea2c 100644 --- a/packages/core/apps/core-apps-browser-internal/src/status/lib/load_status.ts +++ b/src/core/public/core_app/status/lib/load_status.ts @@ -14,7 +14,7 @@ import type { StatusResponse, StatusInfoServiceStatus as ServiceStatus, } from '@kbn/core-status-common-internal'; -import type { DataType } from './format_number'; +import type { DataType } from '.'; interface MetricMeta { title: string; diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.test.ts b/src/core/public/core_app/status/lib/status_level.test.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.test.ts rename to src/core/public/core_app/status/lib/status_level.test.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.ts b/src/core/public/core_app/status/lib/status_level.ts similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/lib/status_level.ts rename to src/core/public/core_app/status/lib/status_level.ts diff --git a/packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx b/src/core/public/core_app/status/render_app.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/render_app.tsx rename to src/core/public/core_app/status/render_app.tsx diff --git a/packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx b/src/core/public/core_app/status/status_app.tsx similarity index 100% rename from packages/core/apps/core-apps-browser-internal/src/status/status_app.tsx rename to src/core/public/core_app/status/status_app.tsx diff --git a/src/core/public/styles/core_app/_globals_v8dark.scss b/src/core/public/core_app/styles/_globals_v8dark.scss similarity index 100% rename from src/core/public/styles/core_app/_globals_v8dark.scss rename to src/core/public/core_app/styles/_globals_v8dark.scss diff --git a/src/core/public/styles/core_app/_globals_v8light.scss b/src/core/public/core_app/styles/_globals_v8light.scss similarity index 100% rename from src/core/public/styles/core_app/_globals_v8light.scss rename to src/core/public/core_app/styles/_globals_v8light.scss diff --git a/src/core/public/styles/core_app/_mixins.scss b/src/core/public/core_app/styles/_mixins.scss similarity index 100% rename from src/core/public/styles/core_app/_mixins.scss rename to src/core/public/core_app/styles/_mixins.scss diff --git a/src/core/public/core_system.test.mocks.ts b/src/core/public/core_system.test.mocks.ts index f5b0c017dcd188..2b378b02554cb0 100644 --- a/src/core/public/core_system.test.mocks.ts +++ b/src/core/public/core_system.test.mocks.ts @@ -21,7 +21,7 @@ import { pluginsServiceMock } from './plugins/plugins_service.mock'; import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; import { renderingServiceMock } from '@kbn/core-rendering-browser-mocks'; import { integrationsServiceMock } from '@kbn/core-integrations-browser-mocks'; -import { coreAppsMock } from '@kbn/core-apps-browser-mocks'; +import { coreAppMock } from './core_app/core_app.mock'; export const analyticsServiceStartMock = analyticsServiceMock.createAnalyticsServiceStart(); export const MockAnalyticsService = analyticsServiceMock.create(); @@ -126,10 +126,10 @@ jest.doMock('@kbn/core-integrations-browser-internal', () => ({ IntegrationsService: IntegrationsServiceConstructor, })); -export const MockCoreApp = coreAppsMock.create(); +export const MockCoreApp = coreAppMock.create(); export const CoreAppConstructor = jest.fn().mockImplementation(() => MockCoreApp); -jest.doMock('@kbn/core-apps-browser-internal', () => ({ - CoreAppsService: CoreAppConstructor, +jest.doMock('./core_app', () => ({ + CoreApp: CoreAppConstructor, })); export const MockThemeService = themeServiceMock.create(); diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 47ea6dd2ec164f..cf3a9e6405f690 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -38,10 +38,10 @@ import { type InternalApplicationStart, } from '@kbn/core-application-browser-internal'; import { RenderingService } from '@kbn/core-rendering-browser-internal'; -import { CoreAppsService } from '@kbn/core-apps-browser-internal'; import { fetchOptionalMemoryInfo } from './fetch_optional_memory_info'; import { CoreSetup, CoreStart } from '.'; import { PluginsService } from './plugins'; +import { CoreApp } from './core_app'; import { LOAD_SETUP_DONE, @@ -95,7 +95,7 @@ export class CoreSystem { private readonly docLinks: DocLinksService; private readonly rendering: RenderingService; private readonly integrations: IntegrationsService; - private readonly coreApp: CoreAppsService; + private readonly coreApp: CoreApp; private readonly deprecations: DeprecationsService; private readonly theme: ThemeService; private readonly rootDomElement: HTMLElement; @@ -140,7 +140,7 @@ export class CoreSystem { this.executionContext = new ExecutionContextService(); this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins); - this.coreApp = new CoreAppsService(this.coreContext); + this.coreApp = new CoreApp(this.coreContext); performance.mark(KBN_LOAD_MARKS, { detail: LOAD_CORE_CREATED, diff --git a/src/core/public/index.ts b/src/core/public/index.ts index e5c137a6d5db4b..9eba054ab53020 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -224,7 +224,7 @@ export type { export type { MountPoint, UnmountCallback, OverlayRef } from '@kbn/core-mount-utils-browser'; -export { URL_MAX_LENGTH } from '@kbn/core-apps-browser-internal'; +export { URL_MAX_LENGTH } from './core_app'; export type { KibanaExecutionContext } from '@kbn/core-execution-context-common'; diff --git a/src/core/public/styles/core_app/README.txt b/src/core/public/styles/core_app/README.txt deleted file mode 100644 index 06f79f0f1afc1e..00000000000000 --- a/src/core/public/styles/core_app/README.txt +++ /dev/null @@ -1 +0,0 @@ -These files are only used by the sass loader, located here: `packages/kbn-optimizer/src/worker/webpack.config.ts` diff --git a/yarn.lock b/yarn.lock index 31c3399f9a387b..ca0826165cf2ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2744,14 +2744,6 @@ version "0.0.0" uid "" -"@kbn/core-apps-browser-internal@link:bazel-bin/packages/core/apps/core-apps-browser-internal": - version "0.0.0" - uid "" - -"@kbn/core-apps-browser-mocks@link:bazel-bin/packages/core/apps/core-apps-browser-mocks": - version "0.0.0" - uid "" - "@kbn/core-base-browser-internal@link:bazel-bin/packages/core/base/core-base-browser-internal": version "0.0.0" uid "" @@ -6735,14 +6727,6 @@ version "0.0.0" uid "" -"@types/kbn__core-apps-browser-internal@link:bazel-bin/packages/core/apps/core-apps-browser-internal/npm_module_types": - version "0.0.0" - uid "" - -"@types/kbn__core-apps-browser-mocks@link:bazel-bin/packages/core/apps/core-apps-browser-mocks/npm_module_types": - version "0.0.0" - uid "" - "@types/kbn__core-base-browser-internal@link:bazel-bin/packages/core/base/core-base-browser-internal/npm_module_types": version "0.0.0" uid "" From cbe7dc810699fd5e2b9e44ca0f8117e15b372190 Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Tue, 13 Sep 2022 21:23:05 +0200 Subject: [PATCH 135/144] [Security Solution][Detections] Rule Preview should process override fields and exceptions (#4680) (#140221) * [Detections] Rule Preview should process override fields and exceptions (#4680) * CI fixes - Types - Unused translations - Unit tests * Fix cypress tests * Fix broken alerts table in fullscreen mode * Update rule configuration state on about step overrides chnges * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * Review comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../cypress/screens/create_new_rule.ts | 4 +- .../cypress/tasks/create_new_rule.ts | 11 +- .../rules/rule_preview/helpers.test.ts | 41 +- .../components/rules/rule_preview/helpers.ts | 21 +- .../rules/rule_preview/index.test.tsx | 141 +++---- .../components/rules/rule_preview/index.tsx | 354 ++++++------------ .../rules/rule_preview/loading_histogram.tsx | 11 +- .../rule_preview/preview_histogram.test.tsx | 14 +- .../rules/rule_preview/preview_histogram.tsx | 27 +- .../components/rules/rule_preview/schema.tsx | 43 --- .../rules/rule_preview/translations.ts | 17 +- .../rule_preview/use_preview_histogram.tsx | 2 +- .../rules/rule_preview/use_preview_route.tsx | 144 ++----- .../rules/step_about_rule/index.tsx | 49 ++- .../rules/step_define_rule/index.test.tsx | 11 +- .../rules/step_define_rule/index.tsx | 198 ++++------ .../rules/step_schedule_rule/index.test.tsx | 22 +- .../rules/step_schedule_rule/index.tsx | 36 +- .../rules/threatmatch_input/index.tsx | 6 +- .../rules/use_preview_invocation_count.ts | 36 ++ .../rules/use_preview_rule.ts | 71 +--- .../detection_engine/rules/create/helpers.ts | 89 +---- .../detection_engine/rules/create/index.tsx | 115 +++++- .../rules/create/translations.ts | 22 ++ .../detection_engine/rules/details/index.tsx | 13 +- .../detection_engine/rules/edit/index.tsx | 105 +++++- .../detection_engine/rules/preview/index.tsx | 80 ++++ .../rules/preview/translations.ts | 30 ++ .../detection_engine/rules/translations.ts | 22 ++ .../pages/detection_engine/rules/types.ts | 16 +- .../pages/detection_engine/rules/utils.ts | 104 ++++- .../public/components/utils/keury/index.ts | 2 +- .../translations/translations/fr-FR.json | 6 - .../translations/translations/ja-JP.json | 6 - .../translations/translations/zh-CN.json | 6 - 35 files changed, 941 insertions(+), 934 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/schema.tsx create mode 100644 x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_preview_invocation_count.ts create mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/preview/index.tsx create mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/preview/translations.ts diff --git a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts index e80e8c210c7c99..4bf39a8bf1d797 100644 --- a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts @@ -170,7 +170,9 @@ export const RISK_OVERRIDE = export const RULES_CREATION_FORM = '[data-test-subj="stepDefineRule"]'; -export const RULES_CREATION_PREVIEW = '[data-test-subj="rule-preview"]'; +export const RULES_CREATION_PREVIEW_BUTTON = '[data-test-subj="preview-flyout"]'; + +export const RULES_CREATION_PREVIEW_REFRESH_BUTTON = '[data-test-subj="previewSubmitButton"]'; export const RULE_DESCRIPTION_INPUT = '[data-test-subj="detectionEngineStepAboutRuleDescription"] [data-test-subj="input"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index a229693ed9f201..bd9c549eb0f40d 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -65,7 +65,8 @@ import { RULE_STATUS, RULE_TIMESTAMP_OVERRIDE, RULES_CREATION_FORM, - RULES_CREATION_PREVIEW, + RULES_CREATION_PREVIEW_BUTTON, + RULES_CREATION_PREVIEW_REFRESH_BUTTON, RUNS_EVERY_INTERVAL, RUNS_EVERY_TIME_TYPE, SCHEDULE_CONTINUE_BUTTON, @@ -336,15 +337,13 @@ export const fillDefineEqlRuleAndContinue = (rule: CustomRule) => { cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).should('be.visible'); cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).type(rule.customQuery); cy.get(RULES_CREATION_FORM).find(EQL_QUERY_VALIDATION_SPINNER).should('not.exist'); - cy.get(RULES_CREATION_PREVIEW) - .find(QUERY_PREVIEW_BUTTON) - .should('not.be.disabled') - .click({ force: true }); + cy.get(RULES_CREATION_PREVIEW_BUTTON).should('not.be.disabled').click({ force: true }); + cy.get(RULES_CREATION_PREVIEW_REFRESH_BUTTON).should('not.be.disabled').click({ force: true }); cy.get(PREVIEW_HISTOGRAM) .invoke('text') .then((text) => { if (text !== 'Rule Preview') { - cy.get(RULES_CREATION_PREVIEW).find(QUERY_PREVIEW_BUTTON).click({ force: true }); + cy.get(RULES_CREATION_PREVIEW_REFRESH_BUTTON).click({ force: true }); cy.get(PREVIEW_HISTOGRAM).should('contain.text', 'Rule Preview'); } }); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.test.ts b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.test.ts index deee988052ef27..8433dbb2fbf876 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import moment from 'moment'; import { DataSourceType } from '../../../pages/detection_engine/rules/types'; import { isNoisy, @@ -14,51 +15,75 @@ import { } from './helpers'; describe('query_preview/helpers', () => { + const timeframeEnd = moment(); + const startHourAgo = timeframeEnd.clone().subtract(1, 'hour'); + const startDayAgo = timeframeEnd.clone().subtract(1, 'day'); + const startMonthAgo = timeframeEnd.clone().subtract(1, 'month'); + + const lastHourTimeframe = { + timeframeStart: startHourAgo, + timeframeEnd, + interval: '5m', + lookback: '1m', + }; + const lastDayTimeframe = { + timeframeStart: startDayAgo, + timeframeEnd, + interval: '1h', + lookback: '5m', + }; + const lastMonthTimeframe = { + timeframeStart: startMonthAgo, + timeframeEnd, + interval: '1d', + lookback: '1h', + }; + describe('isNoisy', () => { test('returns true if timeframe selection is "Last hour" and average hits per hour is greater than one execution duration', () => { - const isItNoisy = isNoisy(30, 'h'); + const isItNoisy = isNoisy(30, lastHourTimeframe); expect(isItNoisy).toBeTruthy(); }); test('returns false if timeframe selection is "Last hour" and average hits per hour is less than one execution duration', () => { - const isItNoisy = isNoisy(0, 'h'); + const isItNoisy = isNoisy(0, lastHourTimeframe); expect(isItNoisy).toBeFalsy(); }); test('returns true if timeframe selection is "Last day" and average hits per hour is greater than one execution duration', () => { - const isItNoisy = isNoisy(50, 'd'); + const isItNoisy = isNoisy(50, lastDayTimeframe); expect(isItNoisy).toBeTruthy(); }); test('returns false if timeframe selection is "Last day" and average hits per hour is equal to one execution duration', () => { - const isItNoisy = isNoisy(24, 'd'); + const isItNoisy = isNoisy(24, lastDayTimeframe); expect(isItNoisy).toBeFalsy(); }); test('returns false if timeframe selection is "Last day" and hits is 0', () => { - const isItNoisy = isNoisy(0, 'd'); + const isItNoisy = isNoisy(0, lastDayTimeframe); expect(isItNoisy).toBeFalsy(); }); test('returns true if timeframe selection is "Last month" and average hits per hour is greater than one execution duration', () => { - const isItNoisy = isNoisy(50, 'M'); + const isItNoisy = isNoisy(750, lastMonthTimeframe); expect(isItNoisy).toBeTruthy(); }); test('returns false if timeframe selection is "Last month" and average hits per hour is equal to one execution duration', () => { - const isItNoisy = isNoisy(30, 'M'); + const isItNoisy = isNoisy(30, lastMonthTimeframe); expect(isItNoisy).toBeFalsy(); }); test('returns false if timeframe selection is "Last month" and hits is 0', () => { - const isItNoisy = isNoisy(0, 'M'); + const isItNoisy = isNoisy(0, lastMonthTimeframe); expect(isItNoisy).toBeFalsy(); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts index 266c0185745af2..6acd2e4db8f947 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/helpers.ts @@ -9,7 +9,6 @@ import { isEmpty } from 'lodash'; import { Position, ScaleType } from '@elastic/charts'; import type { EuiSelectOption } from '@elastic/eui'; import type { Type, Language, ThreatMapping } from '@kbn/securitysolution-io-ts-alerting-types'; -import type { Unit } from '@kbn/datemath'; import type { Filter } from '@kbn/es-query'; import * as i18n from './translations'; import { histogramDateTimeFormatter } from '../../../../common/components/utils'; @@ -17,6 +16,7 @@ import type { ChartSeriesConfigs } from '../../../../common/components/charts/co import { getQueryFilter } from '../../../../../common/detection_engine/get_query_filter'; import type { FieldValueQueryBar } from '../query_bar'; import type { ESQuery } from '../../../../../common/typed_json'; +import type { TimeframePreviewOptions } from '../../../pages/detection_engine/rules/types'; import { DataSourceType } from '../../../pages/detection_engine/rules/types'; /** @@ -25,18 +25,13 @@ import { DataSourceType } from '../../../pages/detection_engine/rules/types'; * @param hits Total query search hits * @param timeframe Range selected by user (last hour, day...) */ -export const isNoisy = (hits: number, timeframe: Unit): boolean => { - if (timeframe === 'h') { - return hits > 1; - } else if (timeframe === 'd') { - return hits / 24 > 1; - } else if (timeframe === 'w') { - return hits / 168 > 1; - } else if (timeframe === 'M') { - return hits / 30 > 1; - } - - return false; +export const isNoisy = (hits: number, timeframe: TimeframePreviewOptions): boolean => { + const oneHour = 1000 * 60 * 60; + const durationInHours = Math.max( + (timeframe.timeframeEnd.valueOf() - timeframe.timeframeStart.valueOf()) / oneHour, + 1.0 + ); + return hits / durationInHours > 1; }; /** diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.test.tsx index 3b635796edd64b..de0d2458a5cfa6 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.test.tsx @@ -7,17 +7,22 @@ import React from 'react'; import { render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; import type { DataViewBase } from '@kbn/es-query'; import { fields } from '@kbn/data-plugin/common/mocks'; import { TestProviders } from '../../../../common/mock'; import type { RulePreviewProps } from '.'; -import { RulePreview } from '.'; +import { RulePreview, REASONABLE_INVOCATION_COUNT } from '.'; import { usePreviewRoute } from './use_preview_route'; import { usePreviewHistogram } from './use_preview_histogram'; import { DataSourceType } from '../../../pages/detection_engine/rules/types'; +import { + getStepScheduleDefaultValue, + stepAboutDefaultValue, + stepDefineDefaultValue, +} from '../../../pages/detection_engine/rules/utils'; +import { usePreviewInvocationCount } from '../../../containers/detection_engine/rules/use_preview_invocation_count'; jest.mock('../../../../common/lib/kibana'); jest.mock('./use_preview_route'); @@ -30,6 +35,7 @@ jest.mock('../../../../common/containers/use_global_time', () => ({ setQuery: jest.fn(), }), })); +jest.mock('../../../containers/detection_engine/rules/use_preview_invocation_count'); const getMockIndexPattern = (): DataViewBase => ({ fields, @@ -38,42 +44,46 @@ const getMockIndexPattern = (): DataViewBase => ({ }); const defaultProps: RulePreviewProps = { - ruleType: 'threat_match', - index: ['test-*'], - indexPattern: getMockIndexPattern(), - dataSourceType: DataSourceType.IndexPatterns, - threatIndex: ['threat-*'], - threatMapping: [ - { - entries: [ - { field: 'file.hash.md5', value: 'threat.indicator.file.hash.md5', type: 'mapping' }, - ], + defineRuleData: { + ...stepDefineDefaultValue, + ruleType: 'threat_match', + index: ['test-*'], + indexPattern: getMockIndexPattern(), + dataSourceType: DataSourceType.IndexPatterns, + threatIndex: ['threat-*'], + threatMapping: [ + { + entries: [ + { field: 'file.hash.md5', value: 'threat.indicator.file.hash.md5', type: 'mapping' }, + ], + }, + ], + queryBar: { + filters: [], + query: { query: 'file.hash.md5:*', language: 'kuery' }, + saved_id: null, }, - ], - isDisabled: false, - query: { - filters: [], - query: { query: 'file.hash.md5:*', language: 'kuery' }, - saved_id: null, - }, - threatQuery: { - filters: [], - query: { query: 'threat.indicator.file.hash.md5:*', language: 'kuery' }, - saved_id: null, - }, - threshold: { - field: ['agent.hostname'], - value: '200', - cardinality: { - field: ['user.name'], - value: '2', + threatQueryBar: { + filters: [], + query: { query: 'threat.indicator.file.hash.md5:*', language: 'kuery' }, + saved_id: null, + }, + threshold: { + field: ['agent.hostname'], + value: '200', + cardinality: { + field: ['user.name'], + value: '2', + }, }, + anomalyThreshold: 50, + machineLearningJobId: ['test-ml-job-id'], + eqlOptions: {}, + newTermsFields: ['host.ip'], + historyWindowSize: '7d', }, - anomalyThreshold: 50, - machineLearningJobId: ['test-ml-job-id'], - eqlOptions: {}, - newTermsFields: ['host.ip'], - historyWindowSize: '7d', + aboutRuleData: stepAboutDefaultValue, + scheduleRuleData: getStepScheduleDefaultValue('threat_match'), }; describe('PreviewQuery', () => { @@ -98,6 +108,8 @@ describe('PreviewQuery', () => { isPreviewRequestInProgress: false, previewId: undefined, }); + + (usePreviewInvocationCount as jest.Mock).mockReturnValue({ invocationCount: 500 }); }); afterEach(() => { @@ -115,26 +127,6 @@ describe('PreviewQuery', () => { expect(await wrapper.findByTestId('preview-time-frame')).toBeTruthy(); }); - test('it renders preview button disabled if "isDisabled" is true', async () => { - const wrapper = render( - - - - ); - - expect(await wrapper.getByTestId('queryPreviewButton').closest('button')).toBeDisabled(); - }); - - test('it renders preview button enabled if "isDisabled" is false', async () => { - const wrapper = render( - - - - ); - - expect(await wrapper.getByTestId('queryPreviewButton').closest('button')).not.toBeDisabled(); - }); - test('does not render histogram when there is no previewId', async () => { const wrapper = render( @@ -145,40 +137,9 @@ describe('PreviewQuery', () => { expect(await wrapper.queryByTestId('[data-test-subj="preview-histogram-panel"]')).toBeNull(); }); - test('it renders quick/advanced query toggle button', async () => { - const wrapper = render( - - - - ); - - expect(await wrapper.findByTestId('quickAdvancedToggleButtonGroup')).toBeTruthy(); - }); - - test('it renders timeframe, interval and look-back buttons when advanced query is selected', async () => { - const wrapper = render( - - - - ); - - expect(await wrapper.findByTestId('quickAdvancedToggleButtonGroup')).toBeTruthy(); - const advancedQueryButton = await wrapper.findByTestId('advancedQuery'); - userEvent.click(advancedQueryButton); - expect(await wrapper.findByTestId('detectionEnginePreviewRuleInterval')).toBeTruthy(); - expect(await wrapper.findByTestId('detectionEnginePreviewRuleLookback')).toBeTruthy(); - }); - - test('it renders invocation count warning when advanced query is selected and warning flag is set to true', async () => { - (usePreviewRoute as jest.Mock).mockReturnValue({ - hasNoiseWarning: false, - addNoiseWarning: jest.fn(), - createPreview: jest.fn(), - clearPreview: jest.fn(), - logs: [], - isPreviewRequestInProgress: false, - previewId: undefined, - showInvocationCountWarning: true, + test('it renders invocation count warning when invocation count is bigger then "REASONABLE_INVOCATION_COUNT"', async () => { + (usePreviewInvocationCount as jest.Mock).mockReturnValue({ + invocationCount: REASONABLE_INVOCATION_COUNT + 1, }); const wrapper = render( @@ -187,8 +148,6 @@ describe('PreviewQuery', () => { ); - const advancedQueryButton = await wrapper.findByTestId('advancedQuery'); - userEvent.click(advancedQueryButton); expect(await wrapper.findByTestId('previewInvocationCountWarning')).toBeTruthy(); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx index 0639fda39ca4da..a5532e176b3c33 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_preview/index.tsx @@ -5,53 +5,38 @@ * 2.0. */ -import React, { useState, useEffect, useMemo, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useMemo } from 'react'; import dateMath from '@kbn/datemath'; -import type { Unit } from '@kbn/datemath'; -import type { ThreatMapping, Type } from '@kbn/securitysolution-io-ts-alerting-types'; -import styled from 'styled-components'; -import type { DataViewBase } from '@kbn/es-query'; -import type { EuiButtonGroupOptionProps, OnTimeChangeProps } from '@elastic/eui'; +import type { OnTimeChangeProps } from '@elastic/eui'; import { - EuiButtonGroup, EuiCallOut, EuiFlexGroup, EuiFlexItem, - EuiSelect, EuiFormRow, - EuiButton, EuiSpacer, EuiSuperDatePicker, + EuiSuperUpdateButton, } from '@elastic/eui'; import moment from 'moment'; -import { useSecurityJobs } from '../../../../common/components/ml_popover/hooks/use_security_jobs'; -import type { FieldValueQueryBar } from '../query_bar'; +import type { List } from '@kbn/securitysolution-io-ts-list-types'; +import { isEqual } from 'lodash'; import * as i18n from './translations'; import { usePreviewRoute } from './use_preview_route'; import { PreviewHistogram } from './preview_histogram'; -import { getTimeframeOptions } from './helpers'; import { PreviewLogsComponent } from './preview_logs'; import { useKibana } from '../../../../common/lib/kibana'; import { LoadingHistogram } from './loading_histogram'; -import type { FieldValueThreshold } from '../threshold_input'; -import { isJobStarted } from '../../../../../common/machine_learning/helpers'; -import type { EqlOptionsSelected } from '../../../../../common/search_strategy'; import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; import { SINGLE_RULE_ACTIONS } from '../../../../common/lib/apm/user_actions'; -import { Form, UseField, useForm, useFormData } from '../../../../shared_imports'; -import { ScheduleItem } from '../schedule_item_form'; import type { - AdvancedPreviewForm, - DataSourceType, + AboutStepRule, + DefineStepRule, + ScheduleStepRule, + TimeframePreviewOptions, } from '../../../pages/detection_engine/rules/types'; -import { schema } from './schema'; +import { usePreviewInvocationCount } from '../../../containers/detection_engine/rules/use_preview_invocation_count'; -const HelpTextComponent = ( - - {i18n.QUERY_PREVIEW_HELP_TEXT} - {i18n.QUERY_PREVIEW_DISCLAIMER} - -); +export const REASONABLE_INVOCATION_COUNT = 200; const timeRanges = [ { start: 'now/d', end: 'now', label: 'Today' }, @@ -64,42 +49,20 @@ const timeRanges = [ { start: 'now-30d', end: 'now', label: 'Last 30 days' }, ]; -const QUICK_QUERY_SELECT_ID = 'quickQuery'; -const ADVANCED_QUERY_SELECT_ID = 'advancedQuery'; - -const advancedOptionsDefaultValue = { - interval: '5m', - lookback: '1m', -}; - export interface RulePreviewProps { - index: string[]; - indexPattern: DataViewBase; - isDisabled: boolean; - query: FieldValueQueryBar; - dataViewId?: string; - dataSourceType: DataSourceType; - ruleType: Type; - threatIndex: string[]; - threatMapping: ThreatMapping; - threatQuery: FieldValueQueryBar; - threshold: FieldValueThreshold; - machineLearningJobId: string[]; - anomalyThreshold: number; - eqlOptions: EqlOptionsSelected; - newTermsFields: string[]; - historyWindowSize: string; + isDisabled?: boolean; + defineRuleData: DefineStepRule; + aboutRuleData: AboutStepRule; + scheduleRuleData: ScheduleStepRule; + exceptionsList?: List[]; } -const Select = styled(EuiSelect)` - width: ${({ theme }) => theme.eui.euiSuperDatePickerWidth}; -`; - -const PreviewButton = styled(EuiButton)` - margin-left: 0; -`; - -const defaultTimeRange: Unit = 'h'; +interface RulePreviewState { + defineRuleData?: DefineStepRule; + aboutRuleData?: AboutStepRule; + scheduleRuleData?: ScheduleStepRule; + timeframeOptions: TimeframePreviewOptions; +} const refreshedTimeframe = (startDate: string, endDate: string) => { return { @@ -109,25 +72,14 @@ const refreshedTimeframe = (startDate: string, endDate: string) => { }; const RulePreviewComponent: React.FC = ({ - index, - indexPattern, - dataViewId, - dataSourceType, isDisabled, - query, - ruleType, - threatIndex, - threatQuery, - threatMapping, - threshold, - machineLearningJobId, - anomalyThreshold, - eqlOptions, - newTermsFields, - historyWindowSize, + defineRuleData, + aboutRuleData, + scheduleRuleData, + exceptionsList, }) => { + const { indexPattern, ruleType } = defineRuleData; const { spaces } = useKibana().services; - const { loading: isMlLoading, jobs } = useSecurityJobs(false); const [spaceId, setSpaceId] = useState(''); useEffect(() => { @@ -144,107 +96,50 @@ const RulePreviewComponent: React.FC = ({ const [timeframeStart, setTimeframeStart] = useState(moment().subtract(1, 'hour')); const [timeframeEnd, setTimeframeEnd] = useState(moment()); + const [isDateRangeInvalid, setIsDateRangeInvalid] = useState(false); + useEffect(() => { const { start, end } = refreshedTimeframe(startDate, endDate); setTimeframeStart(start); setTimeframeEnd(end); }, [startDate, endDate]); - const { form } = useForm({ - defaultValue: advancedOptionsDefaultValue, - options: { stripEmptyFields: false }, - schema, + // The data state that we used for the last preview results + const [previewData, setPreviewData] = useState({ + timeframeOptions: { + timeframeStart, + timeframeEnd, + interval: '5m', + lookback: '1m', + }, }); - const [{ interval: formInterval, lookback: formLookback }] = useFormData({ - form, - watch: ['interval', 'lookback'], + const { invocationCount } = usePreviewInvocationCount({ + timeframeOptions: { + timeframeStart, + timeframeEnd, + interval: scheduleRuleData.interval, + lookback: scheduleRuleData.from, + }, }); + const showInvocationCountWarning = invocationCount > REASONABLE_INVOCATION_COUNT; - const areRelaventMlJobsRunning = useMemo(() => { - if (ruleType !== 'machine_learning') { - return true; // Don't do the expensive logic if we don't need it - } - if (isMlLoading) { - return false; - } - const selectedJobs = jobs.filter(({ id }) => machineLearningJobId.includes(id)); - return selectedJobs.every((job) => isJobStarted(job.jobState, job.datafeedState)); - }, [jobs, machineLearningJobId, ruleType, isMlLoading]); - - const [queryPreviewIdSelected, setQueryPreviewRadioIdSelected] = useState(QUICK_QUERY_SELECT_ID); - - // Callback for when user toggles between Quick query and Advanced query preview - const onChangeDataSource = (optionId: string) => { - setQueryPreviewRadioIdSelected(optionId); - }; - - const quickAdvancedToggleButtonOptions: EuiButtonGroupOptionProps[] = useMemo( - () => [ - { - id: QUICK_QUERY_SELECT_ID, - label: i18n.QUICK_PREVIEW_TOGGLE_BUTTON, - 'data-test-subj': `rule-preview-toggle-${QUICK_QUERY_SELECT_ID}`, - }, - { - id: ADVANCED_QUERY_SELECT_ID, - label: i18n.ADVANCED_PREVIEW_TOGGLE_BUTTON, - 'data-test-subj': `rule-index-toggle-${ADVANCED_QUERY_SELECT_ID}`, - }, - ], - [] - ); - - const showAdvancedOptions = queryPreviewIdSelected === ADVANCED_QUERY_SELECT_ID; - const advancedOptions = useMemo( - () => - showAdvancedOptions && formInterval && formLookback - ? { - timeframeStart, - timeframeEnd, - interval: formInterval, - lookback: formLookback, - } - : undefined, - [formInterval, formLookback, showAdvancedOptions, timeframeEnd, timeframeStart] - ); - - const [timeFrame, setTimeFrame] = useState(defaultTimeRange); const { addNoiseWarning, createPreview, - clearPreview, isPreviewRequestInProgress, previewId, logs, hasNoiseWarning, isAborted, - showInvocationCountWarning, } = usePreviewRoute({ - index, - isDisabled, - dataViewId, - dataSourceType, - query, - threatIndex, - threatQuery, - timeFrame, - ruleType, - threatMapping, - threshold, - machineLearningJobId, - anomalyThreshold, - eqlOptions, - newTermsFields, - historyWindowSize, - advancedOptions, + defineRuleData: previewData.defineRuleData, + aboutRuleData: previewData.aboutRuleData, + scheduleRuleData: previewData.scheduleRuleData, + exceptionsList, + timeframeOptions: previewData.timeframeOptions, }); - // Resets the timeFrame to default when rule type is changed because not all time frames are supported by all rule types - useEffect(() => { - setTimeFrame(defaultTimeRange); - }, [ruleType]); - const { startTransaction } = useStartTransaction(); const [isRefreshing, setIsRefreshing] = useState(false); @@ -256,21 +151,15 @@ const RulePreviewComponent: React.FC = ({ setIsRefreshing(false); }, [isRefreshing, createPreview]); - const handlePreviewClick = useCallback(() => { - startTransaction({ name: SINGLE_RULE_ACTIONS.PREVIEW }); - if (showAdvancedOptions) { - // Refresh timeframe on Preview button click to make sure that relative times recalculated based on current time - const { start, end } = refreshedTimeframe(startDate, endDate); - setTimeframeStart(start); - setTimeframeEnd(end); - } else { - clearPreview(); - } - setIsRefreshing(true); - }, [clearPreview, endDate, showAdvancedOptions, startDate, startTransaction]); + useEffect(() => { + const { start, end } = refreshedTimeframe(startDate, endDate); + setTimeframeStart(start); + setTimeframeEnd(end); + }, [endDate, startDate]); const onTimeChange = useCallback( ({ start: newStart, end: newEnd, isInvalid }: OnTimeChangeProps) => { + setIsDateRangeInvalid(isInvalid); if (!isInvalid) { setStartDate(newStart); setEndDate(newEnd); @@ -279,18 +168,50 @@ const RulePreviewComponent: React.FC = ({ [] ); + const onTimeframeRefresh = useCallback(() => { + startTransaction({ name: SINGLE_RULE_ACTIONS.PREVIEW }); + const { start, end } = refreshedTimeframe(startDate, endDate); + setTimeframeStart(start); + setTimeframeEnd(end); + setPreviewData({ + defineRuleData, + aboutRuleData, + scheduleRuleData, + timeframeOptions: { + timeframeStart: start, + timeframeEnd: end, + interval: scheduleRuleData.interval, + lookback: scheduleRuleData.from, + }, + }); + setIsRefreshing(true); + }, [aboutRuleData, defineRuleData, endDate, scheduleRuleData, startDate, startTransaction]); + + const isDirty = useMemo( + () => + !timeframeStart.isSame(previewData.timeframeOptions.timeframeStart) || + !timeframeEnd.isSame(previewData.timeframeOptions.timeframeEnd) || + !isEqual(defineRuleData, previewData.defineRuleData) || + !isEqual(aboutRuleData, previewData.aboutRuleData) || + !isEqual(scheduleRuleData, previewData.scheduleRuleData), + [ + aboutRuleData, + defineRuleData, + previewData.aboutRuleData, + previewData.defineRuleData, + previewData.scheduleRuleData, + previewData.timeframeOptions.timeframeEnd, + previewData.timeframeOptions.timeframeStart, + scheduleRuleData, + timeframeEnd, + timeframeStart, + ] + ); + return ( <> - - {showAdvancedOptions && showInvocationCountWarning && ( + {showInvocationCountWarning && ( <> = ({ )} - - - {showAdvancedOptions ? ( - - ) : ( -