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 ba2a3fa77e637..44703b4f5707c 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 5eebdd18acfd4..f4b581060e1ef 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 4fd5ebc48e49b..eaef9169925ae 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 ce5b7ee9c5de5..8d5eb34fe580f 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 0d7a23800d404..d15fd7a501ea0 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 1dd795bd795b5..628d2bf14d5e5 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 1e53ba23c39af..ea7d6e0ef4687 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 bd267abb23c7d..d887b72cdb33a 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 ef82aa527bab3..15e72e7aed2bb 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 02abe3a229df4..202a648916081 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 0000000000000..6b8036f2d2393 --- /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 0000000000000..eb52ab17b2f94 --- /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 0000000000000..fa47db412e467 --- /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 eea9acaabda31..9cd711d313a54 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 ec514dfc5b5b1..8325b1a5305ee 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 fe62dd439e3a3..70cf83fbb9764 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 296911022ee90..b96afab404e68 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 69baaee26488f..6401db2a7974d 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 a90c274ce2e86..4ce85f54c3dc5 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 2eee56f15f083..bbb2991551f26 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 c6f651440edb9..b7ef7a4c5cbda 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 2fe24f4440088..4d95846a4f740 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 c5cb4351757a0..81ef6daf184a8 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 945317036e7bc..0c6cf454e73ee 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 078fb0e1442cd..9f425da6475d7 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 5c6979fbd4a03..d17621ade7956 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 00ca0e0a5852c..d0d5fb0cd2cc5 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 5d95d6e7f9446..11d3575a27567 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 38daf27402c54..9a2138786b3a8 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 b8e62a9bed97c..145b9ec56a344 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 67c9bb761be94..33565cd9a34e1 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 fd4830f93159f..daaa2e54ca300 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 6093a2c72a3a9..eaf1bb5d7c5aa 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 15f4d979a7267..f549b07b3850b 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 b382e6905a60f..feed7baf8819a 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 dd22104bf39ad..4ee2bab00f1db 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 affbd9e3357e6..998a356bf4f73 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 9e44561e8b4f5..fa3cda0921c83 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 c32c2282f367e..05f532617d5cc 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 34c41ee2a0024..68ed1082f4c05 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 48dea1e5d4b90..721cd5c73f285 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 c6aad526117cd..d3a1f601445fd 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 d5e77c478aa1d..46956823d1961 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 fae3c4db21737..49a185d6e1513 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 5cf51615a395d..9bc5ce903e2ca 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 6349a33a58fa3..6c5f4a952e9a7 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 56e3ff14ce148..323a6d26acb34 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 396d86e2d6acc..6d4ee5c73c5f6 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 07fd273625d93..5da702eb87797 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 24ccfd3eb01f5..c50ae488383f0 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 c0cd2e351298e..34f0116bb055e 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 96a81ab4f5073..245150f4fb49d 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 cef4740500a97..de45a4cdeeba4 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 01b239ee89b48..94345fa24f377 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 de9606d163944..bee5eca0d7198 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 0699f3d3c3acc..79e9511bbd6f0 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 db054c88cf3ad..eb69c941fa236 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 b0b2292d6b5f1..d21bc53de178f 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 57f30ed8703b0..cecfc60fbbaed 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 069a3e01cdbc1..d4ec14bb29acf 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 94830d71e6337..e494849cc6ceb 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 ace0cece7c981..f68eb647ad88c 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 43b3cbacf2a8d..3f545e9c87229 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 1d8efe71c1530..75b6e829bd3e7 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 120a031c7c912..a1246cc1fa749 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 3e468d7a84ca2..b10cd1b6a1c0d 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 02ceb5b5ebccc..3e1b52cb22f5e 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 2ea72c8604dc6..5cb0404a9d0d5 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 6e8db71b1813d..77eade9df7994 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 96f31e2e8754f..778a1a13e200e 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 e4945f42f8089..c8ea7a0ed2ece 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 d61e3e46a1119..a1d29c8db1363 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 3c78bf954e258..35a5caa7ff9b8 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 f878653430954..ed9f46f96b44c 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 5ca2248ed1ef7..ee3192705332d 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 5ea792e39cb0d..bd8df507c95e8 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 b8712704f11f9..12d140b97e27e 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 26b7ef917f435..2f5b47c824c9d 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 63b777d0dff31..59e7edf1d21d5 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 08bcdbc38c3c5..b564d519e73f9 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 42d0235cbd3a3..24b01c5e0bf03 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 f3275c0b2d73b..6838ef95ce936 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 6e35d801c75d9..c985d5a7af655 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 7f7156284d186..ffddc834dc115 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 d37c4bb72d40e..c37e050b0823a 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 47a1d82c36a15..41db47090cb47 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 4bf28276d1651..323c46a6cbbda 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 1b97987d4a131..1f5e39c532a6f 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 8f873da6d9232..d12fce4efcb95 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 3f545e9c87229..baa85f6fdc93c 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 75b6e829bd3e7..703ecc49772ee 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 a1246cc1fa749..d9f2bb79ffb9c 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 ae40de1b204f4..b223da37daa06 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 40141be799b42..e0a3b8f3a5627 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 a8a1a5403c891..2c4d302d04625 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 8bfc7753efe3f..0730a6435de02 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 03b0d961e1d4c..c8d43207dd5ab 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 6f3958cbb54e1..a59f57e45cdd0 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 686acd5fd048c..0000000000000 --- 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 1e91e4fe462b9..14bfce599dfaf 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 9f425da6475d7..970656933b938 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 11d3575a27567..ea1ecf8c9d652 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 7c73cb4f24508..f7c9352f3a951 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 c4f234b43efd0..f76b446ac72e8 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 0000000000000..edbfa06477ba5 --- /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 371f9a1e79f20..c6a623f19681f 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 775dab6721da1..ef7f1f6540ee5 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 b0c5f8bc7cff9..0000000000000 --- 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 df6286647e82e..0000000000000 --- 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 afa0cfe7e9ae8..0000000000000 --- 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 e8a50c83a3a27..0000000000000 --- 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 e13089dc6404e..0000000000000 --- 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 46956823d1961..0000000000000 --- 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 49a185d6e1513..0000000000000 --- 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 863bd4fcbd35d..0000000000000 --- 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 7aadf6bcfa991..0000000000000 --- 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 5ba4bb2323b24..0000000000000 --- 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 1e0758343ba47..0000000000000 --- 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 bf09bb56bb6f4..0000000000000 --- 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 2e3aa7c4d8d28..6cccf353e4b1c 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 baa85f6fdc93c..7dc55e04a8e3e 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 703ecc49772ee..63d3a23441a0d 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 d9f2bb79ffb9c..68ba5c3825b79 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 dfb018b4bfb5a..20f55a4fffd4f 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 bccb83e63e01b..1007c3f4421af 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 0000000000000..c80f4cd669273 --- /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 a376b4dd5bd48..b998fa5d10db2 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 15241cc5fe890..0497aa54d2eec 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 8c917b4ef6898..868129f3a6737 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 0000000000000..67ff2d3605093 --- /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 1586e47aa1f4c..a005004a90682 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 c9b554fc89031..59808b1df430c 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 ea01e62fbc807..4971dc83c29aa 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 0f791a1f409d1..cdadf9619f008 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 7d1fd0a3d77fe..c2cecdba29b3d 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 b033febcd1ac8..f6afb2bbe033c 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 72dbf3ade5e4a..213f839421a71 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 9eb03dd80e326..a871151ed0b0d 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 81a1dc109b562..8c8629002c93f 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 cdb0ea37a6417..f2a59d6b22b2e 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 09d22022caffd..8afa22d5f695e 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 0000000000000..6b313bdb76c5a --- /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 5b47bbead8300..4a1f91719bca6 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 e868bc99a5417..c5b2e7d1030e6 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 0000000000000..c6bdb2c5a1e77 --- /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 39c288bbbf539..d6b7d96fc112b 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 92ea496e256df..81b2a0e0eb457 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 8e7b7bbcac427..265cc355860d9 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 0000000000000..ade6f8b90d894 --- /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 0000000000000..d07a06e0724cf --- /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 0000000000000..1671e11d4cf2a --- /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 0000000000000..c00ba8f69d805 --- /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 0000000000000..0e9fb14f85468 --- /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 0000000000000..c66de8913b6ef --- /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 0000000000000..6f0484c2044ad --- /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 0000000000000..21a917ea1af6d --- /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 0000000000000..cc65aac74c32e --- /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 0000000000000..cd677e10491ca --- /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 94017b50eb65a..0cbb60531cc36 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 62495ff26d4f4..2896e443e2c37 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 a59f57e45cdd0..622c74efd8281 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 7dad742861ac0..6ac3a0aa7a3ff 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 88ef1152b8f34..ae7c15c73a4d2 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 400642bc1490d..154127f469c96 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 99ce1198f30d7..5a4c346be2e12 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 3b87593d9f483..a7f54ccf701b8 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 ea1448e57398b..2a8d977760cbf 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 bfeccafd2e977..12dfa0f28208a 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 a46a9d8a9397f..afad5b78e9f4e 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 fc6d3f6e7349e..f16feaeb94455 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 0000000000000..9a2763a2f338f --- /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 4f41f95d3a556..659fb7a8216a5 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 b78ad462ae8a1..2a54557b0095b 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 f759830f555fe..0d3f029cc34ce 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 044632a3c3984..23b3da831ddac 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 2658bd7a58b22..96c1983c8f254 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 7dc55e04a8e3e..3e1a916085b40 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 63d3a23441a0d..6c875ca0c2333 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 68ba5c3825b79..05d1f7e1f51e8 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 b3acbf5f51a8a..60a4c2a571a1c 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 94cf19436c3f5..01ebd4433af10 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 05179aa926f86..fc1949549d66e 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 ffe7cb6464123..d30a893ae4c75 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 56a6ee48c3150..1226cbeb3eef1 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 5c410523d70ca..a027db201b002 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 8c650ec9b6051..70fa5f2e8d375 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 cff0b46afcad1..ff8961e263f17 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 6b81c2e499cf4..0000000000000 --- 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 d94adcfe615a5..8b1bf471f4e98 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 e920e43f375b4..3958c1503cd30 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 1b679f285d133..0000000000000 --- 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 cd3174d13c3e6..1f572578119f7 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 ba085b0868216..0000000000000 --- 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 527e3ce64613d..e025bdc339331 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 df7f8750b2ae3..d57d5c4761f6e 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 a88e4dbd01169..0000000000000 --- 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 5dcee56e765e0..b367af4daf492 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 58b77151a9fde..2ae15ca5f83f8 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 9b5fb5424f3fe..26504b07544b0 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 812d22fec913b..da3a104f9ca32 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 a857757f2d864..3064d412da1bd 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 0000000000000..2430b8f2148d9 --- /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 0000000000000..4449e9ca07800 --- /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 bb065a9392d43..29b6fd0446577 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 167c3feb554a7..827a4d6191754 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 e729185b220cc..19e3be94469eb 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 4d12af721a02f..9446fb5dcba6a 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 b60cdf6040b1d..23f8ea83a7094 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 ba830b859d004..8fb3f683e6eb5 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 a2b7a8ad2ce2f..eb651d8aedd12 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 7d2778d602c79..1df471633c3c2 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 659e16dbd0129..5127f0605648c 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 b223da37daa06..e53f8ed64b06b 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 0000000000000..bc9b0aaac6d38 --- /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 0000000000000..b8b0235e9a1e4 --- /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 0000000000000..418aa60b7c1f4 --- /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 0000000000000..8659ff73ced36 --- /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 0000000000000..fe0025102d655 --- /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 0000000000000..3faa6ac609ebc --- /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 0000000000000..8c068d5a162d0 --- /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 0000000000000..da1dc2def3fc8 --- /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 0000000000000..78150b576905b --- /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 0000000000000..764f1f42f52f9 --- /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 0000000000000..a76e8a87c4fe3 --- /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 0000000000000..e2bb6168d1268 --- /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 0000000000000..248dd93ce803b --- /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 0000000000000..4aa41535f4bb2 --- /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 0000000000000..b6e7485e36ab2 --- /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 0000000000000..9fbc3e5c70246 --- /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 0000000000000..d089a5d01f106 --- /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 0000000000000..4687a8e2cb53f --- /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 0000000000000..96c15d715cdee --- /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 0000000000000..a4f1ce7985a55 --- /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 0000000000000..b33071f126efe --- /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 0000000000000..ad806d7d070bd --- /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 0000000000000..5c2d5b68ae2e0 --- /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 0000000000000..323e9848a50a7 --- /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 0000000000000..1a57218f76493 --- /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 e0a3b8f3a5627..03e4ddaace093 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 88fc015ac8b9a..afdfbdfd02eb0 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 aefa4cc90762b..3a3ea87448e64 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 58fb4b5ab559e..c2febf5906249 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 1e103a6b6e4d0..4900a5c9d775e 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 11ce25e0f86f1..70aca733a03d1 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 57f8440c34817..0c6c6f409f848 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 cb0fa6720ff7d..363c30ad83f33 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 efd0974612c59..f5662ee920bf4 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 8cf8174be152f..ed4ad83736d42 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 df23ac288806b..86ec7431bd801 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 497baa999cf2e..d0fb3e3c59dfa 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 51acd123398a7..9685d378556a1 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 04a57ad6ec9f6..4cb233ee0c480 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 a88cffed733a6..b5c999427e1d4 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 013c0473a59b9..b71458c5c5527 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 9d53eb7795943..ebc25aadd21ac 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 a54be7896877e..8d3ba0e73a24c 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 60a4c2a571a1c..b3acbf5f51a8a 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 a48bc7651a1ed..831f0475c2c11 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 863bc82485b81..9eb79190d44e7 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 0e4c0594db3c4..fb7d7646871c7 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 7b77296a7abb9..d5c6c13ca391b 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 8497e2ae833d5..7133dfd6c85cd 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 28fd735f6e461..dc7c5c036cacc 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 5eecc7808e303..21eec3051632e 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 d331897a74bc2..445e6f8b161d0 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 efaf84a5b304a..6c0d9f74ea580 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 27c873e1cbc08..87a44cde46dfc 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 167582665bb6d..fecb09b91403a 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 363cb213dfa2c..31934ad54f169 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 2910180b02cdf..b65e73ac957fd 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 cbc8bc0dcfd44..4ab29be190d88 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 ca9fc19e1213b..f280cd886f807 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 bffc54e20d6ab..7647e574a0489 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 40ee284d2734c..d700f715cd5fc 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 88390589d3835..596ad1ce6d85d 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 ae609d41255ab..4f085837f1317 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 35d2b408052f5..44e4755f2f47d 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 1bd545035359a..8493bbeb60153 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 daf36243e408d..a9828ba77768c 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 d7da06c8bda6e..ed6401ee90e45 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 7e58cc9e1a86a..57403c81c804f 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 f7f878ec5cf74..3fdc8ef0dce57 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 5206f1ec46730..05ce7913fdb1f 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 948da55a39f74..0bd7f60c7859d 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 95fa4182594f8..d31af9be4e4a7 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 19de55351a8de..e9b13996dac8c 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 b1851139b7d9e..8bc524181fa7f 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 892d584ba199e..a222c1751a304 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 2dd8caad2c655..ae2db4b764239 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 df2ac0366eadf..aae826f6eabd0 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 600739e4a9fde..ccddf195d99cd 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 8545316f77c0f..2ca551b49fc6c 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 334a2c08e23c3..090051819ee52 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 6eb89f79f4807..6201c3124a233 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 3ddbd42c2bc73..d6f701b24d111 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 362609d3d6d49..81db63354eed8 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 58bb7cbddd42b..e8be99273583d 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 002dd9eb27139..1f9272fc71406 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 5a45b7486d4c9..520fe453576b4 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 b3f3fc87bda00..890f44f48dfcc 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 0161dd80da0d7..41817a2babd3f 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 8e717efd4ad23..491bb3f165423 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 3867ef968cdda..af0b5490c3e3e 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 f8a6757785b98..3e0211b9f284c 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 9c151c832439f..4794e6477d61b 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 18e588eda0322..8ce939920ce5c 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 7c7fcf1e51a85..491323f11e1c6 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 227caffdd86ae..c4a81fbce9255 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 73127734fb39d..00cdc709d7d43 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 ee91044586ad4..7ce33c3dc8351 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 30188432c4589..e3f630ad08ead 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 abbd5e0f52ab5..65dcbadeb689b 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 ae05b346c5294..680c7be5ac3b4 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 3df0f71990ee1..61096294f663a 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 312da9ec73cca..b59a856511bd1 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 9720c8b749c92..7b984b1b3ced1 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 3bc004877bf6d..c5db0bef7dc54 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 d3bfbec1eafaa..ad7f8812cd8b8 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 47ac9e94ccb6f..864e17ba18d7f 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 00ef1834df39b..b9f59064095fd 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 b94441baeff07..2a3701b79c6d7 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 212a823589def..c444592ed14ab 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 151db33c2bbd0..838b35681ace2 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 0633e4a824850..b81ea75cfaaf8 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 7cd6a257eeca1..dcda22c9b4e00 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 b83bcf59070e4..a7983f72580bc 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 05616b0cfadc4..09d0183b9151d 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 8454800519cb0..4a00d6265c95d 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 100b024c58ddf..5edde61b03b30 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 4606d800cf22e..c6419c2f9a0db 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 765ff1f91971f..4c04ff932864d 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 4b51bc25be890..d846738129acd 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 d5a04ff5eee17..aad3ebee73970 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 a99efc95e8c13..5239dceb0b4b1 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 1fd92e71b327a..3549300cebec0 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 4f9fac4a0b2ec..f31e192ad5409 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 ada937d1aa30e..6dcf2355e3322 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 360208b56403b..3abb48ffa29f9 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 995d23de7fcc7..596bbea03e8a7 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 41246db0a6756..b29cb6fc67bf4 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 82c57310848d5..f667c80691840 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 3b8859bf24577..2429ab10684b2 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 a84beaaf76f9c..b09e1e8ec196f 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 f81ea7eb893f4..c993682371dd1 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 f136b1b4b9722..34ab9ce22db43 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 4fac55f5f28f2..a656c6f017a59 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 9a986e49442eb..62069d98c5550 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 ad805a672ec6a..4086bede91f50 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 d48d41a5c8649..8bfb510cb4fa1 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 1e6fbb0c52619..5a928943d1e94 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 4ed5acbd873d2..d5e32b85b786f 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 1a85935c87425..84f3f19cf92ec 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 ac39a7961593a..457bb48fbcdc1 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 fc5cd3bfb8438..0afa1ba825240 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 4c9c75e852390..baad9a7e2452d 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 92c1424297816..3e71f0cc873c7 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 da3c85dc76a4e..1d1dafb69871b 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 e291353f701f6..31d93967d234d 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 e1d48305d2290..06c0a6252f860 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 1b208d9a63487..167b9518fbfdd 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 3ad4f503057fa..027dc4ea5eb7b 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 4779f2f4f68b5..b3a70181b0c2d 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 701892c07d6fb..f96bd7d5c5e6e 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 5a164327bf338..e5fae7dc02d76 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 6f65974f3df95..368a5dd0008ca 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 3ac31dbf66d23..6d155ce49d85e 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 5d9da0822c070..66f5f7450be48 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 0fb84b17ee969..3ce0e791b7464 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 24dc0372c51ec..7c6f27244f0d7 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 a52d64e5e6e20..3849e728af3e2 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 5e2bfe3318f47..91a0837f38318 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 8e3c4efe990f0..724e892be1c60 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 ecc9bc1bad7b3..25d6e2dae632f 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 fa73a6310dd90..5727d5efa48df 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 e9d543f5eab88..39ec5296fe70e 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 5e380c589df45..74e947bc8463d 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 86d55e1e9c44d..e91fb82f80610 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 6dd116c3c46f2..70564fe13edbb 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 96418b9c64b68..91f7162c82f7e 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 b557d4e5c473a..8073bb4836752 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 0cacd094cfbb9..5678298ca733c 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 2c72b3d00c599..96f7ecec3bc42 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 1582e2b3c6a47..824030f1daa25 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 7cad22cf1928b..db5d060f35a8d 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 ac6c785eb5bbc..1780ab586e649 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 65546108902bd..11ccbdd98c2f3 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 b119bfb2ad808..c698d02940bcf 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 d8d8afa63313d..0c8b555c77721 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 7bb38a3c5f0bf..92e416c29bf95 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 da30359337d2f..37c2becd7354b 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 115eabde42da7..390a061c8981c 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 edfcddc56edc1..b42023a54f615 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 6d3b3e2cf0095..9ab334b2c6624 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 fcc2284968ba8..8787f12bceadf 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 48919a14adc5d..95ff1d8689a57 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 0a87811f9fa6d..aea2f328723ab 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 be640b0bd6c12..f3764fe8d6f94 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 4d9363ee6d067..3a1182ada5065 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 8e1632be18c1b..a4cc0208bd03f 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 7fee5984f817a..a4d41b900aef8 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 c989c3c38eff4..c638049a6b3e0 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 ab44b913d6d22..ea182d13d4240 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 a23bfab235572..db770a72f3597 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 cc4ba299fcd2f..264b5b1a33166 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 f3ad4235ca0bd..1403f95b83599 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 8e03645953472..f387d4a897882 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 cd7e2beebf898..96020064f61fb 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 355ed41119b58..1315293ec65a2 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 bca3d59fc66ba..e1f3750c84a27 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 8c1ce95e5da38..53e3dbb94f360 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 9855a467f8ff3..9af745103bea0 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 e10bab2bb0ef1..b8f73ee93016a 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 6bbcf9a1ed58f..89a06be37a6fa 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 ca0b28fad3b83..a396a416f9d74 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 d0b3e5f8750ae..7140c88921d6f 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 09595678ffd95..2164762ea7a02 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 f98bc4b4caa51..828f4f1a12d5f 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 2d6f60b30b0f4..c836a584e0095 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 7d6d538a4a345..daf159516318b 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 965b44c3d7f49..b19ffe7e38b18 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 baf526633cb7f..cd01fd5273929 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 c7e3e793271dc..150968cb0570e 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 ba256a3dc7685..788e4f701670f 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 20ddad2be7f37..8101e973753e8 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 6278558d4a15b..94799690c450d 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 774dbb4aa58f2..7a3515639112e 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 b68f29089b3c5..c2a89783ff233 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 9da56c2b13d54..3635d788ab55c 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 fc5ad5407ea58..9e3162a0eee92 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 cbc248a380a6e..4c2b69880d9b7 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 6c389f91fb1de..b89677d1be743 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 e8223e2b45977..742de4384ddd0 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 2c27b78aff6bb..8621952d15a63 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 197b80b4ba630..518d5c12f5d68 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 bf9b1d6b28607..6210a65c92159 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 21561dfeb133d..2f7ec5fe4f2e0 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 d4790272c355d..e9a8d04e8c462 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 1e44984b977ae..0cb0033765ac1 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 064c1a7409c91..08c1e192449f6 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 68d8ba8c77e35..c1665898b331d 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 33c45bca370db..50fa0b1303d19 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 8fb776cf68240..01133a602b616 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 37b831645698d..63a4b1b1afc78 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 b1e0f26591dea..0052df5199754 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 76e6857265343..fb4b4c5e40025 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 b0656d2d7698c..0c7b97f3d40aa 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 ecd8eb6b89e58..8a0f130084dcc 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 3095a10b0e8a3..57a308d4daba9 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 6e6235f54d936..0585dfbd2b21a 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 9ba194c06f4bd..20980722e5e60 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 841d63be63be4..0f69c3872f40b 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 62ca0892a8ef0..b67d4011f24c5 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 6db912ca3d51d..1444f1dc2beba 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 124ba03f2d7cb..a20cf1a5fb3b9 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 436795ec64440..c5399214f2edf 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 d39b682d0e922..3560b5d875cc3 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 097b612967b60..60d095cdc0842 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 5cfc809e628d4..8c065c5e187c6 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 0735565b60ba3..e48205627b908 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 0000000000000..b49607b86963e --- /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 0000000000000..bde6925ddfcf2 --- /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 0000000000000..39b4d63b9e25a --- /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 0000000000000..f8b8988e0f703 --- /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 0000000000000..6438e27aa69d3 --- /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 0000000000000..92b56d4cc62fe --- /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 0000000000000..d24cd2e143830 --- /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 0000000000000..2d6ea32e7361d --- /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 0000000000000..85f331d9e7e27 --- /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 0000000000000..bdfe6900db761 --- /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 bcc58ce97c172..f21f50e4be1fe 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 fab15b3ed6f35..15647342dddb0 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 017403c279a71..36e37f77a6194 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 4b18d3cb540b5..fe02ab842adba 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 d68eda65b7478..ca47234632782 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 d43b64677389a..a6c20f54519d5 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 a2b638ea5c8f3..acc89049462fb 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 6a7ad1ab8e14d..66cb9a0b33eb0 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 9b16f81a2be4a..662fd7c508ba7 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 135387c16286c..8c88455d9b092 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 cb5b74bd34c0b..13bab0f2ea1fc 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 02f152900b447..5d4a2904c9b54 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 70e8d69a6b17c..2c449d15974bf 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 77788c27073dc..01d0f9a9a6a32 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 669752ea17991..dfea5cf2ab202 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 653e1b5efe544..85cc9c38bd331 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 f7edb115f49a9..95b42536984fa 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 f83c97ef5f49d..e841f9170a1fd 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 7278c02638113..f23422a1b253a 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 044c765674ea1..57fbccecd3fdd 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 d47c4a94ac534..d4b4c39f2de25 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 5cc4b3d097f4f..cbf92ce5c9634 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 5cad59a4b8f74..ae6572d784a59 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 ca0ada5848034..7a52f9e558bfd 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 792b606b4133a..b7944a7d94e9e 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 6e1eb7f3fcfde..6040010dd50e4 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 3fa74decb5caa..c9cea912963a8 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 5c3fcdaab984c..a129022994df3 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 ed9435a3b3b74..b578add112d05 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 3e663271b7a7d..fa2b54e14253b 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 89013d791f80d..a538f4419085b 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 03c70dae79e77..2d7dfddb7cfde 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 4f6ed6ee570a8..78bd769b5616f 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 0d51ff6ce1465..4555f95d1db3a 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 dda867b946f49..f4bb9bdaa32f2 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 1eeda889c5cdd..305d42d10b555 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 8c87bc7a914bd..9ff24d656b6f5 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 1f89b3b7e535a..c4eced5115fbc 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 6885069422ac0..6eee5a2ddc959 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 771d6d1341fca..d449b34a0d001 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 eb7eb96ae58c2..41fdb074db308 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 c778ebc86da32..88fdd1d8a30cd 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 f9799e1ac3947..4d281617212ea 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 fc653bed6e7e9..ccd82c4552dab 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 12b0ecb60e66c..c277f36bd6890 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 67f7ef712b419..b8068d9717b68 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 a8aa07a6cb0ad..5fad0d1b3c619 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 cf5344b7847eb..e02e85e387df3 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 59384f2ce9406..b26e5b25de93b 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 cb5c6845f2d4f..236351581f68d 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 2445802229bf1..24abda1b0c6e7 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 617d5fec736bf..e01f3f99ffd81 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 44df77707e11d..6e2679e6ac26d 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 6917f3fc99b3b..e7571b2b5f2db 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 9b30733e7280b..e31a33e2ae566 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 d278bd47a83cc..d96fa6a177e2f 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 e1c8c47ea5d19..47327f749fc93 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 d2a1be19c6c17..c6699b94b8a39 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 e4fbf89a1405f..1820e21e88d48 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 38f823267cd07..b5c97c6c0e198 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 adec0fb8b5efb..5f500a432f34f 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 cf020e8b0a27a..256a659190289 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 598a866af57e8..ed97855cf3548 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 7f8c8c6110751..2b84ca3272b69 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 3690bc8cbc2b4..9f7dcd57ae65a 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 e30499cbbf39a..abd918eb8d398 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 22657a04b1bb9..4a53f6921c66c 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 19a2c081a5bd7..426a1bbc586ab 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 65f02eb6305e7..17dd013084ddd 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 f84326704b432..c1a403fe7e707 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 2553be04e72c4..be4755193af44 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 e1deb3f5d47f7..7554a6a18493d 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 e28e8dfe7c35a..142a54239e551 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 57ee3c5eaeeac..1797e343347d8 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 823e9843677a0..8364ea1f8c53b 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 27455c0dcff20..26110f7aa404d 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 30e9422c7d0dc..ffa50fa47a0f7 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 d382db6b06181..757355b8211db 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 f719f64919ffe..726fe4c091d14 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 6c98183d2a7ff..dc28f2e50ce65 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 e96fd6b65b797..5a0615a5e3b88 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 f082939bf23db..128001d9f7a5d 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 56d513e6b2395..a491b3eef50b9 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 f2aa470f834cc..eb074d07ee15b 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 003b096cfd0f9..7b3a8439e29e0 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 8b61bc3b8fb03..1b151f3099a00 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 9b0e41366e492..7690985e6c9f7 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 673f7aa80d418..5c27ce9906bfd 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 fca609edd1eec..08f8c0ea2414f 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 d55f975104ffa..b7b14058fc47e 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 370bb3fb7b081..4670ab6757530 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 0000000000000..b3381733e9f8f --- /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 0000000000000..90e7d25f00b89 --- /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 0000000000000..db66a62441697 --- /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 0000000000000..5dff7d8731cd4 --- /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 9200b11a09b21..aa5ef51758ba3 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 d281f952bbbdf..194fe83ad1f38 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 ce6cfca9bcf5c..5a16ff03fb990 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 ef9f4272e5ae1..105a4ef0ec531 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 5e5cd15a35874..71ffb06e4a78f 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 f09537bfe88ae..05262ee2da854 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 9bd71879017ce..99e1dfc8e1cb0 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 9a002696753d0..cf3152a814a0d 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 5b0eba5853c13..6e824fa356773 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 3a4cf723d0775..f36daceb7cab2 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 2b1cfb4d5c2fe..aa87ac4e7d912 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 20c4a3eb4f9ba..9de5f0f3f5929 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 fb392e818e687..6285f1eac7ef0 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 c06226b8eba96..6d71d005ef887 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 b81adb3a56d1d..93d680eec7468 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 e75d872f2484d..53fbfddd18b59 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 b70ee2231fefb..fa8178a8e940e 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 b7ddf660ca0df..32cbe5fc75ada 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 92cd97760ca7c..e594effff18d1 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 af84fa702b075..4d779ad075df5 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 c6f2cc8482954..5027bcad2b28b 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 789133a70ac7e..a18c550e61132 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 4ea296d9ab1e1..952430c15e7dd 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 d69d9e8545c96..934fab6cb77a2 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 169dcb7ee1f23..3db1b04623d64 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 7f3978dab8e03..cc1da70e18508 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 a22c71323b68c..9c97fda0e603c 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 571dc8691bd0a..8289ecb41a7b2 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 201e1c21dffbc..b2739110c8138 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 d00e7742b2ed4..683099eee4fec 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 751f7ca0cd136..c66d0b73906be 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 9a598bdde11fb..03690c74dc10f 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 fb06fd880fdb0..b3579c2abc9d0 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 ff860e62ea1b9..3381ec2ec9efc 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 ed642dcfa50a6..b20466ec2a997 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 ddf5e67004844..1fc969c65cd8c 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 6fb7aa53be7c7..c7f924e8ba2bd 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 e92a9aab1928c..564b741812351 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 ef7c19dc1b7fe..79c9eda7c7be5 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 680c70e75c060..b37b1655b9065 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 7a1e6c0e0601f..99becab9902a4 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 8398670e49a38..1947693a47766 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 f6762a00b3cc2..27b2acef31bce 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 bd88e5f88c6ff..bc7c76f0a0c95 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 4dc8865027be9..88da0bf6a4084 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 98619fec51a28..74b1dd2f9b3d7 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 32c76e983e404..79ae29b7cd963 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 0c20752827038..5d356a047e0f8 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 3da2926bef45d..8e691c449fa90 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 ccb2436bc7ab5..fb05689cecd02 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 8ebb9e956a9bd..3e1a0c5cac8db 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 96fc861f282ec..4b92df6269c8f 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 f1f07a53b63c0..b478c993aec5a 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 10469dabcc739..d066af233eaa0 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 e0fd13863fddb..67f6e1447557d 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 ab9308881edad..e997282c0b6e0 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 25835a28fb913..6d738d3ef7b25 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 7aeaddd49f9fc..d77a427d28d03 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 f2e9de3b4461d..850b23354ce98 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 a0b46b34aff8c..4bd6c8ea81ccf 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 917ac7b5c8b7a..fbd92de7c18e3 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 3d2d4e9f7d91b..c8c3606dd8e9b 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 039252a8b5f89..a0a381d3172c4 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 e1bbb20979c05..b2619a5e99e09 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 6f5a5d420ec86..d2905a302b374 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 fe725f5cd654d..c804bf9990136 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 c510c72159d82..49f4d89ec5bd8 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 79bcdf8736b5d..5b29098952f77 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 a79d78af7bd71..594bd8e6e2514 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 5a830485f55ec..03ffe572bc60c 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 e8be0345a839f..729e3cc82c26e 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 d53e2f51177d7..ec7747ab73d4e 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 97a09460258c2..0f3ecb6391ebb 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 e95f3879bfb83..15625ed9a811c 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 477dcd64c4e87..75e2299f8583e 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 f2fbbc473c25c..926dbd529e6e1 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 c14315f59ce5a..73636fd0965d1 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 74c9ed470c1f1..abbad21fb3a9d 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 b9c921a284d1d..c086fe973e1ec 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 4de9f1cf325bf..747a230f0e7c6 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 d497f6bb0a446..c59213764f79a 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 1237c1960ae3b..273e849b4a232 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 54d7da6ff41a9..20c8ee5c76e45 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 48c4485641f9b..0d13f8c5ebd84 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 f03b8bea14f0b..4dba7024de942 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 db63128f3733e..7d4ff7d4b09f0 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 3767eed28f79c..517a86689b15a 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 eaa8be6fe9eaa..0b81c3a76a286 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 56642da0d7bb1..44dac9a54417c 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 20e284f805f36..0f7d4fcd62492 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 d7a9c73ca0265..706467a384a47 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 d708564591c58..4061ad954517b 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 d5c6c13ca391b..3025e3c667a60 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 7133dfd6c85cd..a9f6922f31c0d 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 dc7c5c036cacc..877f5f0d59912 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 445e6f8b161d0..969deada62d83 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 87a44cde46dfc..031ff7c280dc6 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 fecb09b91403a..e02969f5caba7 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 31934ad54f169..d6497fb8300dc 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 b65e73ac957fd..f02bf545e8e1c 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 4ab29be190d88..e383d536d3839 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 f280cd886f807..8a9e27d98094a 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 7647e574a0489..c5c83271b18d3 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 d700f715cd5fc..fb001228fa3f4 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 596ad1ce6d85d..b9047f4a24a4a 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 4f085837f1317..6da5ee9f0746d 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 8493bbeb60153..204d2415d2b7e 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 a9828ba77768c..8cd3ce3704b80 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 ed6401ee90e45..1c7d146485765 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 57403c81c804f..aae133a241220 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 3fdc8ef0dce57..c211da19b2a49 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 05ce7913fdb1f..ade7e083d84bc 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 0bd7f60c7859d..f6c931e4cec1a 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 d31af9be4e4a7..6744db8e790c7 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 e9b13996dac8c..224ac3dfcb2dd 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 8bc524181fa7f..d5d199ff46ba1 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 a222c1751a304..9b05096958466 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 ae2db4b764239..24fee647eeb7f 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 aae826f6eabd0..0e9744507654c 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 ccddf195d99cd..a350a7959739a 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 2ca551b49fc6c..5ebeeae4c53dc 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 090051819ee52..7b8f1654a1d64 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 6201c3124a233..1d250c38c549c 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 d6f701b24d111..d12e6c092ab7d 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 81db63354eed8..f382a16c0f09f 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 e8be99273583d..a2e50f21c7e26 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 1f9272fc71406..b1d1432f6b4c7 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 520fe453576b4..ecde934e30aff 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 890f44f48dfcc..976cd3fddd097 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 41817a2babd3f..b9ce5e2524833 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 af0b5490c3e3e..b914b0c80cf12 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 3e0211b9f284c..8a494564e676a 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 4794e6477d61b..4e9ab427950b2 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 8ce939920ce5c..e4fe738d7d291 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 491323f11e1c6..c71511b96c318 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 c4a81fbce9255..33ba87eb7b5f3 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 00cdc709d7d43..3bfd49a0a0ab5 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 7ce33c3dc8351..f1d49dc44f8dd 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 e3f630ad08ead..b6d68cb2b323e 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 65dcbadeb689b..c6b1df89b1360 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 680c7be5ac3b4..b2e2ad2f8444e 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 61096294f663a..c150b5f41465f 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 b59a856511bd1..28f009516b419 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 7b984b1b3ced1..56897b6597827 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 c5db0bef7dc54..5a8e3138f0812 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 ad7f8812cd8b8..e038774bfa937 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 864e17ba18d7f..92e0207fbd8be 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 b9f59064095fd..60ec7732acd75 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 2a3701b79c6d7..a6d8d632ff9b0 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 c444592ed14ab..c53e062e643a8 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 838b35681ace2..5ed82a919fcd6 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 b81ea75cfaaf8..5bbe2b58a1acc 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 dcda22c9b4e00..0a59397f0c068 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 a7983f72580bc..81c7981454742 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 09d0183b9151d..4920906b8fcdd 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 4a00d6265c95d..9c5867adf2e44 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 5edde61b03b30..e75e271da43f1 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 c6419c2f9a0db..a86d6e9cba7a5 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 4c04ff932864d..757980d3e6c93 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 d846738129acd..0b69c7a96e6c4 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 aad3ebee73970..7f5fa0c4a8cd7 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 5239dceb0b4b1..2b5a1eed6ec3f 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 3549300cebec0..ec2a36eb92df7 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 f31e192ad5409..f75dae8740f9a 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 6dcf2355e3322..d4a81f43dc82f 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 3abb48ffa29f9..429b53bdf7e10 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 596bbea03e8a7..4c4cb3cf3efa2 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 b29cb6fc67bf4..f1e62abb86ab1 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 f667c80691840..4e062859cb0b1 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 2429ab10684b2..a7a506ce86fc2 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 b09e1e8ec196f..6b570ab3aab8c 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 c993682371dd1..0cfd4d21feb79 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 34ab9ce22db43..fc833e10f2685 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 a656c6f017a59..e26a00304d9a0 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 62069d98c5550..cf6f7a950ad55 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 4086bede91f50..eb21786d914dd 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 8bfb510cb4fa1..01f5e595c9dd3 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 5a928943d1e94..52bc3424f9e01 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 d5e32b85b786f..79413342ab401 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 84f3f19cf92ec..a85abe0d1f462 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 457bb48fbcdc1..91991ec18f884 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 0afa1ba825240..473131110b37d 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 baad9a7e2452d..5109686b45e4b 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 3e71f0cc873c7..94e10b46f2316 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 1d1dafb69871b..bc0f9edc66671 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 31d93967d234d..ba57a73b99942 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 06c0a6252f860..3fa4da5936b38 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 167b9518fbfdd..51c111c7988f7 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 027dc4ea5eb7b..1b76d387f4509 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 b3a70181b0c2d..f6e23ad2b383c 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 f96bd7d5c5e6e..07637ebdaf7c0 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 368a5dd0008ca..d35d7443a193e 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 6d155ce49d85e..34e28daec02d0 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 66f5f7450be48..c739147712e76 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 3ce0e791b7464..0461dd4be981f 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 7c6f27244f0d7..2e725a6344536 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 3849e728af3e2..430137c8d9959 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 91a0837f38318..fce198d30b8a7 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 724e892be1c60..083977d68e52f 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 25d6e2dae632f..80d5650610242 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 5727d5efa48df..6ac42a81cccaa 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 39ec5296fe70e..d81872b86ed9f 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 74e947bc8463d..74d33cc2a26e2 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 e91fb82f80610..6a273e0bbc640 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 70564fe13edbb..2dc2bbdec82d5 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 91f7162c82f7e..2cfda1b1e14f5 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 8073bb4836752..26aee3b1d9481 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 5678298ca733c..daf442ebc26b4 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 96f7ecec3bc42..7a1c650f01e58 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 824030f1daa25..c1d20b550cd00 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 db5d060f35a8d..3af31403f23ac 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 1780ab586e649..9b92df3210b12 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 11ccbdd98c2f3..b1ef52b7dc5e7 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 c698d02940bcf..b7cebd8cb7869 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 0c8b555c77721..d5a72fb8c9f7a 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 92e416c29bf95..d8e28509d3f6d 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 37c2becd7354b..a20a4f29e6235 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 390a061c8981c..dbc1a29005b26 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 b42023a54f615..64faca1523441 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 9ab334b2c6624..a8866f07127b8 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 8787f12bceadf..2cb03493086ef 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 95ff1d8689a57..e806ee84139e5 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 aea2f328723ab..2de4c4665618d 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 f3764fe8d6f94..7e486b492cb7f 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 3a1182ada5065..0c29cdee5039d 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 a4cc0208bd03f..fabbeb65d0a48 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 a4d41b900aef8..c977778112ccb 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 c638049a6b3e0..c8454f5f4a1ad 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 ea182d13d4240..f90f61f344182 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 db770a72f3597..644f37bab4f8b 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 264b5b1a33166..73c5b5e7ab616 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 1403f95b83599..90a1d70ad8ebe 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 f387d4a897882..41fa8208a1d3d 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 96020064f61fb..07e62ce040bee 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 1315293ec65a2..0e1f4bc4292dd 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 e1f3750c84a27..9c661db0a0d4c 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 53e3dbb94f360..fdffc72c5de1c 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 9af745103bea0..adcf42480843b 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 b8f73ee93016a..f99d83106c9ba 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 89a06be37a6fa..00f2319d95a4d 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 a396a416f9d74..2036346943a3b 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 7140c88921d6f..2430f7709e3f2 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 2164762ea7a02..e9e57ae24900b 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 828f4f1a12d5f..193a70ee06f5c 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 c836a584e0095..4d4bde98c0824 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 daf159516318b..6b8cf748eea9b 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 b19ffe7e38b18..b470dc449dd95 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 cd01fd5273929..23ce8cc600f0e 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 150968cb0570e..fa7a24d11ac1f 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 788e4f701670f..f137c3dccec8a 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 8101e973753e8..8911ce825c348 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 94799690c450d..f4f423d7181cb 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 7a3515639112e..a99659d4c5b9f 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 c2a89783ff233..d0ea7ef610155 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 3635d788ab55c..239347724a16b 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 9e3162a0eee92..38f9308d18924 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 4c2b69880d9b7..c4091bcd35f9b 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 b89677d1be743..7e34262d8bb25 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 742de4384ddd0..4ae04538bb07e 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 8621952d15a63..7ceeca5e39b67 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 518d5c12f5d68..8b580261d449b 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 6210a65c92159..5de3e5441f0a3 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 2f7ec5fe4f2e0..c9a8a6fa296fb 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 e9a8d04e8c462..e21ba36217cdb 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 0cb0033765ac1..24be1762c920d 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 08c1e192449f6..a441e2ef32789 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 c1665898b331d..8a5919dd59d97 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 50fa0b1303d19..b838876f7f747 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 01133a602b616..bfcbeb55a18b8 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 63a4b1b1afc78..66abe1a392701 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 0052df5199754..904a4b379dcf1 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 fb4b4c5e40025..1fc8fea5658de 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 0c7b97f3d40aa..4db9b280efd7a 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 8a0f130084dcc..bf1cb01f73a28 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 57a308d4daba9..1afe62c5c2ce8 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 0585dfbd2b21a..70950894bcedc 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 20980722e5e60..59dc76b98636e 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 0f69c3872f40b..5892c9fb0a016 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 b67d4011f24c5..c407dcb5e295a 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 1444f1dc2beba..dc9525f01b09b 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 a20cf1a5fb3b9..2ce5252fd39df 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 c5399214f2edf..2ffdb6dc3ce24 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 3560b5d875cc3..2b67fbdd40722 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 60d095cdc0842..e3395e86dae43 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 8c065c5e187c6..bbff1bf85dbbd 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 e48205627b908..396a6320edec5 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 bde6925ddfcf2..e538113de3fac 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 f8b8988e0f703..58ed0073a4cd9 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 92b56d4cc62fe..36d33ea9b1a74 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 2d6ea32e7361d..687cebf362c2a 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 bdfe6900db761..0c8d201b108db 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 f21f50e4be1fe..01b7c9b754726 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 15647342dddb0..2c23d98be0d55 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 36e37f77a6194..ae8a3bb99e231 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 fe02ab842adba..f66d8b9d925c2 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 ca47234632782..60daee6a7d7e5 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 a6c20f54519d5..6a9cf22463b09 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 acc89049462fb..cbf6d68698872 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 66cb9a0b33eb0..400a2273ebb48 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 662fd7c508ba7..a580f88ebdfe1 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 8c88455d9b092..74de25b9936b3 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 13bab0f2ea1fc..45af778aabb7a 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 5d4a2904c9b54..cc570f84b5efa 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 2c449d15974bf..189fd0164bfe1 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 01d0f9a9a6a32..436322f785428 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 dfea5cf2ab202..7a5442a1a0cae 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 85cc9c38bd331..e9fa94182c598 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 95b42536984fa..3218754cc239c 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 e841f9170a1fd..010511da8532e 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 f23422a1b253a..d9e2807bff893 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 57fbccecd3fdd..cd39f7f26935e 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 d4b4c39f2de25..3b1835f359eb8 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 cbf92ce5c9634..597ccfe2be00e 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 ae6572d784a59..1604ebb3ec2e3 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 7a52f9e558bfd..1bf6e2f7f5a00 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 b7944a7d94e9e..e24c7591af75b 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 6040010dd50e4..4215f85c6f8c5 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 c9cea912963a8..c9bfd3ca76b14 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 a129022994df3..ba1864c2dc58d 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 b578add112d05..645ca3d359c8b 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 fa2b54e14253b..ddd1905cc7047 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 a538f4419085b..99dd8ebca1653 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 2d7dfddb7cfde..d9efa7441aa9b 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 78bd769b5616f..936f1dee9f1e4 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 4555f95d1db3a..05349d6c8ba5c 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 f4bb9bdaa32f2..529512b81500c 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 305d42d10b555..ec7d13bd2af08 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 9ff24d656b6f5..fa53134892561 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 c4eced5115fbc..d72524950d40e 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 6eee5a2ddc959..c30d18c57d28f 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 d449b34a0d001..088b7c3ab3e51 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 41fdb074db308..3b262cbc1a1e8 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 88fdd1d8a30cd..d0805d8f0e3a7 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 4d281617212ea..49721d1cea988 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 ccd82c4552dab..1156a351ae27f 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 c277f36bd6890..f96c7fb58804f 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 b8068d9717b68..306793a3ad557 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 5fad0d1b3c619..fb0f0be2270ff 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 e02e85e387df3..7591ffa38ef80 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 b26e5b25de93b..322849b06d34f 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 236351581f68d..c9b0d4fe6a0ac 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 24abda1b0c6e7..668f0851dbfa5 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 e01f3f99ffd81..bd11c64056cf7 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 6e2679e6ac26d..cd76e179c4559 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 e7571b2b5f2db..2e09a5e871c85 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 e31a33e2ae566..415a5ae710a72 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 d96fa6a177e2f..9807368001ea3 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 47327f749fc93..2db12aca59f5e 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 c6699b94b8a39..8857544c0305a 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 1820e21e88d48..d9498bc90ca62 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 b5c97c6c0e198..9d7b8f7633c3b 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 5f500a432f34f..8670181ea2618 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 256a659190289..dae3809a97f6e 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 ed97855cf3548..45dc38e5c6942 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 2b84ca3272b69..e5f1b8291164b 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 9f7dcd57ae65a..8f20caaeb9cae 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 abd918eb8d398..8344e032aad54 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 4a53f6921c66c..f1bf9b4131302 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 426a1bbc586ab..ade345bb5615d 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 17dd013084ddd..447ee7b71c7e2 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 c1a403fe7e707..5c71c74ae942c 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 be4755193af44..10400f212cfcf 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 7554a6a18493d..0fee8a03fa870 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 142a54239e551..f0b51e26b5ad6 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 1797e343347d8..2609283ac184e 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 8364ea1f8c53b..08fc271620859 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 26110f7aa404d..81c4323ef5b3f 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 ffa50fa47a0f7..c6b4f08bec31a 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 757355b8211db..f827d296d95f7 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 726fe4c091d14..76fa4162e4659 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 dc28f2e50ce65..e6532bbf960c5 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 5a0615a5e3b88..52ccc629f932c 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 128001d9f7a5d..34dac5295a708 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 a491b3eef50b9..21df75d4ceec4 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 eb074d07ee15b..5cf068205b142 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 7b3a8439e29e0..9975f552e2d18 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 1b151f3099a00..fd907ad4acd66 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 7690985e6c9f7..8f006ae13ac7f 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 5c27ce9906bfd..ae83d0e7fe3b7 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 08f8c0ea2414f..9e345e8fb66ff 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 b7b14058fc47e..d60e9ac96d280 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 4670ab6757530..96cc446e6fefb 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 90e7d25f00b89..24567ffdf3445 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 5dff7d8731cd4..46ecfc817267f 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 aa5ef51758ba3..8af04a8805463 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 194fe83ad1f38..0150f05323bba 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 5a16ff03fb990..c6fa1e5cc264d 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 105a4ef0ec531..fae6e16ab92a5 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 71ffb06e4a78f..8e8ab3618f788 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 05262ee2da854..faf5cee741994 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 99e1dfc8e1cb0..8751ba41cac84 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 cf3152a814a0d..2e430f9d0266d 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 6e824fa356773..17572df236341 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 aa87ac4e7d912..6d6d8317f0e55 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 9de5f0f3f5929..f4d7dd3e0f4e1 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 6285f1eac7ef0..8c5ef3203612d 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 6d71d005ef887..078368ad36013 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 93d680eec7468..df03b17c3ae0f 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 53fbfddd18b59..9e9f1254c7461 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 fa8178a8e940e..cce7fbc5689fd 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 32cbe5fc75ada..594491fdecc8b 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 e594effff18d1..36d9451444b3e 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 4d779ad075df5..4feba3b38f759 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 5027bcad2b28b..a157a01b3c9a6 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 a18c550e61132..a97469db4181d 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 952430c15e7dd..e1be4466c01de 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 934fab6cb77a2..50f5703693a3d 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 3db1b04623d64..52b62a9bc69a4 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 cc1da70e18508..25d86a53be826 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 9c97fda0e603c..573d944ceebb5 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 8289ecb41a7b2..fc72f81f23e7b 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 b2739110c8138..01d17ee704f7c 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 683099eee4fec..b0c5f348b512b 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 c66d0b73906be..9e0b6900d2097 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 03690c74dc10f..157780cd018b8 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 b3579c2abc9d0..3319ee23629ef 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 3381ec2ec9efc..e9978c6653cb9 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 b20466ec2a997..c3fb959fdf6b5 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 1fc969c65cd8c..07fad65fc3b27 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 c7f924e8ba2bd..bb16b57ac9e24 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 564b741812351..fd9c6c30b99a1 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 79c9eda7c7be5..c788ba9e7f623 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 99becab9902a4..db53834bfe134 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 1947693a47766..07b26fd92d2b6 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 27b2acef31bce..c12a7b23b50da 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 bc7c76f0a0c95..e8fcd477b4023 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 88da0bf6a4084..c2adbf5d4b688 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 74b1dd2f9b3d7..ec9abe0f75103 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 79ae29b7cd963..b36bcf7dcf04d 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 5d356a047e0f8..fcb98184ac721 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 8e691c449fa90..2d29a830ac210 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 fb05689cecd02..54366ae393ceb 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 3e1a0c5cac8db..01b865e133a77 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 4b92df6269c8f..ed0eb8d662405 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 b478c993aec5a..c26048db69289 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 d066af233eaa0..e3f02c8e02988 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 67f6e1447557d..a6487b3702381 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 e997282c0b6e0..4a39fa9cdd561 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 6d738d3ef7b25..74ba599fc51b3 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 d77a427d28d03..81eee14edb1fb 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 850b23354ce98..dad1dd94bbd4d 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 4bd6c8ea81ccf..22fac81e89023 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 fbd92de7c18e3..07e5942620fc3 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 c8c3606dd8e9b..a775f63cffd49 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 a0a381d3172c4..ec94eb7b7ec89 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 b2619a5e99e09..4124b57346329 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 d2905a302b374..3bc27698a6036 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 c804bf9990136..66be10fc270cd 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 49f4d89ec5bd8..75102dbc52f82 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 5b29098952f77..c848059af41e0 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 594bd8e6e2514..2d383534e6173 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 03ffe572bc60c..3f6612eeb7090 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 729e3cc82c26e..601adbcdf9383 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 ec7747ab73d4e..55b6299dfd477 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 0f3ecb6391ebb..e69614e09b29e 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 15625ed9a811c..603903b5e1684 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 75e2299f8583e..f82809f791062 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 926dbd529e6e1..a44e9ef13c884 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 73636fd0965d1..a03b99f1f280b 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 abbad21fb3a9d..46cbdd7c38354 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 c086fe973e1ec..e435391266471 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 747a230f0e7c6..514bfd452f0c4 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 c59213764f79a..5e0571a91b3be 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 273e849b4a232..88ceeaf9a67b0 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 20c8ee5c76e45..b4590576a445e 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 0d13f8c5ebd84..688644059d558 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 4dba7024de942..e683cc9d59d0c 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 7d4ff7d4b09f0..65bd5ac3f83eb 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 517a86689b15a..569b354b761a6 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 0b81c3a76a286..362e6fa9159ff 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 44dac9a54417c..de331861fc09e 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 0f7d4fcd62492..197508c600b5c 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 706467a384a47..e4d1de0d28a31 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 4061ad954517b..72cff108cef00 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 3ed54c451f38b..96afe9deb98e2 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 e3516f982cc0b..2938251e177be 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 40eb009a71bd1..7a67c6fdeb65b 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 9b8d012e7b084..ddea34a936178 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 5e158c51c02d1..ff464e7782bb7 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 15c6fa645de11..bc039b334a910 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 927d408884d20..ba56cfa0da62d 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 0000000000000..7b6949696bbee --- /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 69c4befec1b6c..c19dd10802f32 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 5148dde4d6b59..4e9ff49a2b1dd 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 c7f8481c36247..494ecb0c6b4d0 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 0000000000000..7b96f3886159c --- /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 0000000000000..3517bbf7643d3 --- /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 0000000000000..fe7b811bd70fd --- /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 0000000000000..32305a5916c04 --- /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 0000000000000..77e2f14c51420 --- /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 126f057742901..4999d757cd047 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 b34338b4cbce9..065ac297ee468 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 27208dbaed00e..6961086edac1b 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 377f12fd63208..666588dd09886 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 3025e3c667a60..e89fd0e7ed367 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 a9f6922f31c0d..a6de0eddd53d6 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 877f5f0d59912..db20b98ed0f6a 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 969deada62d83..d46ff5aa181b5 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 031ff7c280dc6..371251c3d2f6b 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 e02969f5caba7..48441c7541f20 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 d6497fb8300dc..051acd0e75900 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 f02bf545e8e1c..a0952458e0f45 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 e383d536d3839..dbd163dff3005 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 8a9e27d98094a..94a6853c57cce 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 c5c83271b18d3..67f888cd10fab 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 fb001228fa3f4..2d93e7b6a7ef6 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 b9047f4a24a4a..885e264937e68 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 6da5ee9f0746d..07fbe27b7c048 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 204d2415d2b7e..9d6e782717324 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 8cd3ce3704b80..604f24762a12b 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 1c7d146485765..454aa521d5942 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 aae133a241220..125f6303237f3 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 c211da19b2a49..bb06789a9d338 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 ade7e083d84bc..e862a2588c40d 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 f6c931e4cec1a..247b776e53e30 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 6744db8e790c7..594122e246d10 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 224ac3dfcb2dd..2881eb78d6fbd 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 d5d199ff46ba1..fe964392680cd 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 9b05096958466..35957ede2cc4f 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 24fee647eeb7f..63c9c3051d4e4 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 0e9744507654c..d9ba036f7bbe6 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 a350a7959739a..07f70de66a166 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 5ebeeae4c53dc..4a9e44b189a79 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 7b8f1654a1d64..6ab2af56de8a6 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 1d250c38c549c..c21e6fc7a14bd 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 d12e6c092ab7d..844946af12dba 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 f382a16c0f09f..6d0f630e84048 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 a2e50f21c7e26..cf1334edf5db3 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 b1d1432f6b4c7..31c161302239c 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 ecde934e30aff..337602bc8deb6 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 976cd3fddd097..88767bde098f9 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 b9ce5e2524833..bfb01ed547536 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 b914b0c80cf12..67fc800a393f5 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 8a494564e676a..55e41dee84df0 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 4e9ab427950b2..272f14fa331c1 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 e4fe738d7d291..883e69752d7c2 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 c71511b96c318..2fd851509964a 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 33ba87eb7b5f3..dd3e3a7c1b9c4 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 3bfd49a0a0ab5..ec3bd2846e1a8 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 f1d49dc44f8dd..323af21664b16 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 b6d68cb2b323e..ce8b70c802891 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 c6b1df89b1360..44d11e482c899 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 b2e2ad2f8444e..170818628b752 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 c150b5f41465f..ba84f73e3531a 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 28f009516b419..a1190ad13be1a 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 56897b6597827..e58dcecd23eb3 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 5a8e3138f0812..be93903834285 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 e038774bfa937..7084d5dd8614b 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 92e0207fbd8be..a3a2ffc66d724 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 60ec7732acd75..5acb5094dcbe3 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 a6d8d632ff9b0..d2657f3258452 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 c53e062e643a8..deb8f6162875b 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 5ed82a919fcd6..3318c54d6b6f9 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 5bbe2b58a1acc..ad5da6eb52715 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 0a59397f0c068..a566a62d1f846 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 81c7981454742..5285ccf531912 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 4920906b8fcdd..96c41a5268b4d 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 9c5867adf2e44..28ccaee3ae731 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 e75e271da43f1..e2601319591a4 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 a86d6e9cba7a5..1e71960980198 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 757980d3e6c93..f55d67c1fc3dc 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 0b69c7a96e6c4..89439f8a35a2a 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 7f5fa0c4a8cd7..132c55a0f5320 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 2b5a1eed6ec3f..023dcb2b4bb36 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 ec2a36eb92df7..e491c482cb629 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 f75dae8740f9a..c4ba600af1dab 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 d4a81f43dc82f..bb77b10ad5c55 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 429b53bdf7e10..1aa6719c6e313 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 4c4cb3cf3efa2..180b6a7699ad3 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 f1e62abb86ab1..4b863396dbcf4 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 4e062859cb0b1..01a492a721e05 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 a7a506ce86fc2..14b01e3c7be4a 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 6b570ab3aab8c..a129e1b408e44 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 0cfd4d21feb79..dc390f25f0170 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 fc833e10f2685..741443fe91e35 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 e26a00304d9a0..40098db9d607f 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 cf6f7a950ad55..4d457a94dff83 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 eb21786d914dd..75ad6cf16351d 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 01f5e595c9dd3..988bba727b23c 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 52bc3424f9e01..f308239b6d475 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 79413342ab401..0714ab8c48ebf 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 a85abe0d1f462..1cd0b626f5510 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 91991ec18f884..7777a057c2894 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 473131110b37d..b85fd73d4c901 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 5109686b45e4b..8937453ad90ef 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 94e10b46f2316..21d0c98603bd5 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 bc0f9edc66671..5bf553a6b4e27 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 ba57a73b99942..84e37926b9d2e 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 3fa4da5936b38..08601a43abe02 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 51c111c7988f7..42e241da77343 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 1b76d387f4509..5600e432ddde8 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 f6e23ad2b383c..36b74b926858b 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 07637ebdaf7c0..53392790ff321 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 d35d7443a193e..4596828c8a7f7 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 34e28daec02d0..8c56c35df8037 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 c739147712e76..e369bc6cf9573 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 0461dd4be981f..a02516d41e635 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 2e725a6344536..4cf9fbbbd4890 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 430137c8d9959..ed7cb4116ff68 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 fce198d30b8a7..d6275075f4f2d 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 083977d68e52f..8b8b3352b3e03 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 80d5650610242..26b3493760d23 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 6ac42a81cccaa..6aeec78a9de0b 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 d81872b86ed9f..cb3d85753a695 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 74d33cc2a26e2..3f5b097166b70 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 6a273e0bbc640..c3308a653104f 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 2dc2bbdec82d5..b77b28d64156f 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 2cfda1b1e14f5..a4c4c5108d54e 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 26aee3b1d9481..6d190e7921922 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 daf442ebc26b4..adcb25e4e3b65 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 7a1c650f01e58..a2fc67402f23e 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 c1d20b550cd00..125a8ddb62eb2 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 3af31403f23ac..490c09706c8aa 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 9b92df3210b12..8507ca2cb3903 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 b1ef52b7dc5e7..9aa393700f1cc 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 b7cebd8cb7869..64475b318c506 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 d5a72fb8c9f7a..3b16e74a4edd2 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 d8e28509d3f6d..19bafc1b112da 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 a20a4f29e6235..2afd793f95c19 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 dbc1a29005b26..7e71e344bbf24 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 64faca1523441..36cab5deb51a2 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 a8866f07127b8..1a6af787887d5 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 2cb03493086ef..ca61b99d2dbab 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 e806ee84139e5..177fc4c26f4ae 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 2de4c4665618d..4200bb38465cc 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 7e486b492cb7f..b95726bae4f8c 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 0c29cdee5039d..96baa43f4f803 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 fabbeb65d0a48..9d90489b193a2 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 c977778112ccb..dc43d1ef8ebe2 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 c8454f5f4a1ad..72d95cc2173bb 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 f90f61f344182..2604bdf1307f6 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 644f37bab4f8b..a70c8ebdd2038 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 73c5b5e7ab616..090d7dea7fc90 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 90a1d70ad8ebe..062468ef28b45 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 41fa8208a1d3d..13666c7455aa7 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 07e62ce040bee..8f122bb2f056e 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 0e1f4bc4292dd..7bf289e5bff95 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 9c661db0a0d4c..d5afd2459cb6a 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 fdffc72c5de1c..643fc21c88e99 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 adcf42480843b..337c83d0c71ed 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 f99d83106c9ba..41b228a782728 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 00f2319d95a4d..23037163144c5 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 2036346943a3b..13949e3052dc5 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 2430f7709e3f2..35d1ab22608d6 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 e9e57ae24900b..0145a71c0d7b2 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 193a70ee06f5c..87346ec4fa5b7 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 4d4bde98c0824..d9ba50274fda1 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 6b8cf748eea9b..90e86fc55e65b 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 b470dc449dd95..60f31535742b4 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 23ce8cc600f0e..302e26129c712 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 fa7a24d11ac1f..337f272c28fe5 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 f137c3dccec8a..8d4b519f59c14 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 8911ce825c348..196c31459d3f2 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 f4f423d7181cb..730e06acc610b 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 a99659d4c5b9f..11c953906f0dc 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 d0ea7ef610155..a5ba2bcf8c3cc 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 239347724a16b..75f3667db69e4 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 38f9308d18924..ace513c8f3fd6 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 c4091bcd35f9b..ee9a394184d4e 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 7e34262d8bb25..5333d41e14584 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 4ae04538bb07e..4a89b92fff036 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 7ceeca5e39b67..14247d429667c 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 8b580261d449b..0e8f65ff9da07 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 5de3e5441f0a3..52483dfa4dc6c 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 c9a8a6fa296fb..857037bab1093 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 e21ba36217cdb..b2767486e6592 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 24be1762c920d..6afb7d61f7327 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 a441e2ef32789..23ae70cfd0c9f 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 8a5919dd59d97..7a3a3d003792f 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 b838876f7f747..23db97bef04a9 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 bfcbeb55a18b8..f7574d68fb4aa 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 66abe1a392701..fb970d77d9a9b 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 904a4b379dcf1..71eb12db08bbc 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 1fc8fea5658de..d84f5c5c73c7e 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 4db9b280efd7a..93ab71cd6d0c2 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 bf1cb01f73a28..089cea7cbcd40 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 1afe62c5c2ce8..ac8a36714f9c9 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 70950894bcedc..afa0e5688428d 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 59dc76b98636e..fbecff8bedc44 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 5892c9fb0a016..56315c20f6063 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 c407dcb5e295a..ae5b78204d1b8 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 dc9525f01b09b..0b3f8c2f078bc 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 2ce5252fd39df..e2f35211ba038 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 2ffdb6dc3ce24..c13d91d1c3d3b 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 2b67fbdd40722..6e430a5fa2611 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 e3395e86dae43..06e6a2ecbe278 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 bbff1bf85dbbd..f6aecda23d6f1 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 396a6320edec5..5fac3e3216d8a 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 e538113de3fac..1743916cfc825 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 58ed0073a4cd9..f815aa153ef38 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 36d33ea9b1a74..30a90ae7a976a 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 687cebf362c2a..1b1bcdac498dd 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 0c8d201b108db..d2a4f74edd929 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 01b7c9b754726..7fecf1916746c 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 2c23d98be0d55..794d64d7e64e9 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 ae8a3bb99e231..f0d5725c883fa 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 f66d8b9d925c2..65edbdba1a628 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 60daee6a7d7e5..d9f583d515cfc 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 6a9cf22463b09..925ad46a92610 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 cbf6d68698872..10165c0389dd6 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 400a2273ebb48..fed0b546122cd 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 a580f88ebdfe1..0732415264371 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 74de25b9936b3..5052cc57dc19e 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 45af778aabb7a..79a90a07cb013 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 cc570f84b5efa..60c5375cd230d 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 189fd0164bfe1..34d1cab6fdcee 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 436322f785428..cc0de7274d49f 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 7a5442a1a0cae..59692fd76e326 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 e9fa94182c598..b29893225438d 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 3218754cc239c..a95ffcdf1e28b 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 010511da8532e..5daa6d13cf6a3 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 d9e2807bff893..e76afe4af60ff 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 cd39f7f26935e..0fde4b55f119e 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 3b1835f359eb8..2644e4c3b5e71 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 597ccfe2be00e..beefe799a31bf 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 1604ebb3ec2e3..59951f466f831 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 1bf6e2f7f5a00..cce2805a4412c 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 e24c7591af75b..db4ae2018ca5b 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 4215f85c6f8c5..28ee9c2cff91c 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 c9bfd3ca76b14..136a0dd3d55f0 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 ba1864c2dc58d..eb5455dd7d830 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 645ca3d359c8b..40b7ac766e87a 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 ddd1905cc7047..57561b5cbc50f 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 99dd8ebca1653..d2c265790b9b4 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 d9efa7441aa9b..2bf014a652c69 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 936f1dee9f1e4..c2c4c4d0337a8 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 05349d6c8ba5c..4049be82b4dfb 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 529512b81500c..306996d8dcc16 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 ec7d13bd2af08..e7387cd969eff 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 fa53134892561..dbc89d69930c2 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 d72524950d40e..943a7e8f6ee37 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 c30d18c57d28f..42d8da1b6627e 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 088b7c3ab3e51..dca53916d65b6 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 3b262cbc1a1e8..6ba7fb075d16d 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 d0805d8f0e3a7..2832f3e8dae4b 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 49721d1cea988..9860f16923015 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 1156a351ae27f..aff7a4c3270b2 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 f96c7fb58804f..a162aa944dc67 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 306793a3ad557..875e36a1a9991 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 fb0f0be2270ff..9a84263750a9f 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 7591ffa38ef80..c7162db39b87c 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 322849b06d34f..8b0c2dce899c4 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 c9b0d4fe6a0ac..eff3e884b3bd7 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 668f0851dbfa5..3fdf23cd53c02 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 bd11c64056cf7..37bb135d5c280 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 cd76e179c4559..a5383cbc3b530 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 2e09a5e871c85..ba7590ffbe159 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 415a5ae710a72..017f82899a837 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 9807368001ea3..49f9e90702310 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 2db12aca59f5e..ebe0a2779fedf 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 8857544c0305a..15d8fcc4196ee 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 d9498bc90ca62..a3eb896fea4c6 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 9d7b8f7633c3b..db43ecbf5d190 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 8670181ea2618..3fa0a82da7e87 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 dae3809a97f6e..90ed9b37626b4 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 45dc38e5c6942..43dbe59c8b441 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 e5f1b8291164b..79e9918ff415a 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 8f20caaeb9cae..4260459c9d064 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 8344e032aad54..d7da0dc87559b 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 f1bf9b4131302..93b46261b29ac 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 ade345bb5615d..73955118e002c 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 447ee7b71c7e2..e0d4fb5f40c7d 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 5c71c74ae942c..ce83347c99d76 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 10400f212cfcf..aaee03632d3bd 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 0fee8a03fa870..72c05e4c8e597 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 f0b51e26b5ad6..5396d1d529cc3 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 2609283ac184e..ebeb4c6b525a9 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 08fc271620859..af5b4f23845c2 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 81c4323ef5b3f..6fbaa004f2aa1 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 c6b4f08bec31a..216b4ec105498 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 f827d296d95f7..86b17203dd3aa 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 76fa4162e4659..ba2a281401304 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 e6532bbf960c5..fc4bed4b1a001 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 52ccc629f932c..d0c9c5ed9392b 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 34dac5295a708..f6aa153d98fd1 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 21df75d4ceec4..967834391e6dc 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 5cf068205b142..527b5039281e5 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 9975f552e2d18..b132757f0b152 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 fd907ad4acd66..92be11cf2c6b6 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 8f006ae13ac7f..579464a3146de 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 ae83d0e7fe3b7..c89f5a58f576e 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 9e345e8fb66ff..f7430ec4cffc9 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 d60e9ac96d280..770abdeea3c3d 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 96cc446e6fefb..f20bc874aa489 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 24567ffdf3445..c88c99fdfa8e1 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 46ecfc817267f..ad038875cef83 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 8af04a8805463..008ba2f53e93c 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 0150f05323bba..7883d6366d4f3 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 c6fa1e5cc264d..c7fe9875c57c6 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 fae6e16ab92a5..bc834ee2ff41a 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 8e8ab3618f788..1dd32b08c95c5 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 faf5cee741994..a76ec2f91fad0 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 8751ba41cac84..ffd690fb8d542 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 2e430f9d0266d..6d4cee2cf48e5 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 17572df236341..bb0e1cfdac9b0 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 6d6d8317f0e55..bbfa64010e3ba 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 f4d7dd3e0f4e1..762df9d42c29c 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 8c5ef3203612d..957ed8febfcae 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 078368ad36013..98103fbb8df50 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 df03b17c3ae0f..ff85afae240ef 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 9e9f1254c7461..9e427901caff1 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 cce7fbc5689fd..6900408be11c0 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 594491fdecc8b..cd577edea97f4 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 36d9451444b3e..cbe25e33be509 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 4feba3b38f759..e2a850694866b 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 a157a01b3c9a6..e09f9577b2b03 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 a97469db4181d..a789dd3553362 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 e1be4466c01de..8af7864ea4939 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 50f5703693a3d..cb45d6c5a4431 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 52b62a9bc69a4..0de39481f8629 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 25d86a53be826..1652626d9f56f 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 573d944ceebb5..6e43b6db2c76b 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 fc72f81f23e7b..48955617613a9 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 01d17ee704f7c..8c8b8e8c9ef66 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 b0c5f348b512b..1f36b3105cdc8 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 9e0b6900d2097..a726ebc34c5fb 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 157780cd018b8..74513f78d1f36 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 3319ee23629ef..a5fb71bb58e91 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 e9978c6653cb9..7cac92107a18c 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 c3fb959fdf6b5..616e1e5a07fc7 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 07fad65fc3b27..afe72ce3daf47 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 bb16b57ac9e24..c2674d018305b 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 fd9c6c30b99a1..ac8837b6ca894 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 c788ba9e7f623..ba58d7518c6e4 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 db53834bfe134..c580985bc8887 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 f217e15c771ef..8d45fc77730ef 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 07b26fd92d2b6..1e938d796a4a7 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 c12a7b23b50da..40d73b16b018a 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 e8fcd477b4023..ecf895a3e0f7a 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 c2adbf5d4b688..9d61b29944ba9 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 ec9abe0f75103..286139d6fe63f 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 b36bcf7dcf04d..3a26281e749b6 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 fcb98184ac721..c9236042b14f0 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 2d29a830ac210..d04909af54896 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 54366ae393ceb..03f4861574ec8 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 01b865e133a77..312293e55cc62 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 ed0eb8d662405..e629a877e6a51 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 c26048db69289..456808d926a82 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 e3f02c8e02988..8dc7f9e54649e 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 a6487b3702381..15f259f2794d4 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 4a39fa9cdd561..5c308f8c268e9 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 74ba599fc51b3..47f80ea4bfb32 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 81eee14edb1fb..e1d55dd7b8f5e 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 dad1dd94bbd4d..29a07610f1e5c 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 22fac81e89023..9c8e4190bf491 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 07e5942620fc3..6bd52414173b9 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 a775f63cffd49..1e59aff6842ba 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 ec94eb7b7ec89..02b72e1835c09 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 4124b57346329..85ade27d7ba7e 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 3bc27698a6036..696dc5d871335 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 66be10fc270cd..3a62678f11769 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 75102dbc52f82..30f763ba4488f 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 c848059af41e0..f56b57fe0398c 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 2d383534e6173..80abde5c72bc8 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 3f6612eeb7090..8e620fcd48321 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 601adbcdf9383..020d59da436aa 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 55b6299dfd477..27facd7cbc791 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 e69614e09b29e..6b6af45f6d599 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 603903b5e1684..68f0239219c7a 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 f82809f791062..f9e3c5956fea5 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 a44e9ef13c884..82043a2029661 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 a03b99f1f280b..5b3a5638c74ef 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 46cbdd7c38354..bebe8e757136a 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 e435391266471..ba4d70200d714 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 514bfd452f0c4..eac1395483f26 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 5e0571a91b3be..ac07b7b6dec90 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 88ceeaf9a67b0..27386a94c37aa 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 b4590576a445e..c25eb47e0fbdc 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 688644059d558..492e3f940e990 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 e683cc9d59d0c..bd06921b3a740 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 65bd5ac3f83eb..32a53d10810cc 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 569b354b761a6..1a0fe74391504 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 362e6fa9159ff..faaeaad6e7c4b 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 de331861fc09e..9892ae3945683 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 197508c600b5c..d2862d4828d21 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 e4d1de0d28a31..8c22d419a997c 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 72cff108cef00..eb856d91fcbba 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 a0c5212244ad6..1e6d7b40b22d0 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 9df9702eb0870..7d685369e4d10 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 ebc25aadd21ac..cb9690ca3dc8d 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 d67e12cf8eccc..9f29f3ba7f69f 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 8c77d4fd013c1..f9e95080c92e4 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 6ea883f7a560d..2041d5fe500fc 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 c2f55847e7d1e..a90932595d42a 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 fbd4310489fef..614a776423079 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 2de87bdb660f7..7cf3fb779942c 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 2af55809f1c91..05be275af41c0 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 f76343156c955..00cbd0a2ffcb0 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 08a0296ad8c08..bd47c072e7735 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 614a776423079..68b2553478df7 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 8c9c690924218..945ab9b85a4f1 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 0000000000000..bade9615b630d --- /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 1c68844079fa6..059170d9702d8 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 930864091c2eb..63696a3a2196c 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 0000000000000..db585f5f28204 --- /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 924f678c1f96b..3f30eb64ff2c9 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 778a1a13e200e..5d68e29a88d08 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 6f838631591ce..a68f09cba6a54 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 ad3b3c94ac6da..05eb4966496a0 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 75cd1f9cb9f94..0000000000000 --- 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 2696ad60a4568..63280d230b777 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 9e85d6e4cbf7a..ccc4ada609d03 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 9fef8ae47b3b0..2ae40c2e33961 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 add4c1c206dd4..c607eb2985af8 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 0000000000000..1166dbed8ca88 --- /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 dceb8fd0f30a7..a180fb942bd15 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 d8aedbc10bd3d..c38408c8f5417 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 3c056ccf996dd..ce38c82f08384 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 0000000000000..6ffa18cfa8073 --- /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 0929f8971cf06..be5b8ace2e2b6 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 8e5263a31ff3d..38f0b9d53b1d1 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 4c477e1b4a581..23a8772852e17 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 cedd7c9b64718..25da22f9be168 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 8715af5d6fa68..9e593fa6c282a 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 284785b33d720..3855f14134f46 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 0000000000000..fdd4b5cb77e7d --- /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 0000000000000..520c76fef5124 --- /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 db5411525290b..74ff651a0a11c 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 1e935c15891f4..647763d5461d1 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 c85f989f88281..0dd651f6c9251 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 0000000000000..d7b61e16b36b6 --- /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 0000000000000..b9ee1dd871b8e --- /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 0000000000000..27115acf5697f --- /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 0000000000000..cb824adf0a217 --- /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 70f9e7d2fbdfc..ab3b0f90c65a6 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 33620c91d87a2..9180244b9cf45 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 0000000000000..2ff593651abf7 --- /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 0000000000000..be4efc0edfed9 --- /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 78f5a4e9d5c54..d34e216c34af9 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 6d8520e61a493..8b45258889e5c 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 c455ae0c3628d..ee2d2d9a4468c 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 8f67b3c05d3e4..c54e3206b2b01 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 d72b1cc523f0d..59cf8f919606b 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 7e0f7e5a6b9d5..780a1bbd1d02f 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 3d7be7f08084d..5db400203468a 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 73f466aeec771..0000000000000 --- 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 7e6d9e2b05d94..0000000000000 --- 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 f36996c013471..e2893cbbc5aa8 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 707cb9b7c4335..c5c7ddcaab875 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 ec8a84de1aa88..dd27a4a91ca12 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 d31c297d18b1c..d9ba8890aab31 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 0000000000000..57cde43c9fee6 --- /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 42580ede0b3f2..e0a499df05633 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 ef5b4418d454f..d559a0981ad69 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 60fc0e92d024b..0991156cd3d4d 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 4a6bc85c7cbd7..1517450c4f62e 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 b3a7909b06929..b963947a6282d 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 d5553a3f6f13d..f9d0203a5647f 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 b5b5d902d3a4d..91425c368286d 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 8ba409468851e..7477e6df8d5dc 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 d7db17bd97cbd..23d952738aa4d 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 0000000000000..fec173ac70c61 --- /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 0000000000000..4abd9f276abaa --- /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 0000000000000..3c0c935d9316e --- /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 73610e5959345..a2c713d5a9abc 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 0000000000000..3471aad3fec3c --- /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 0000000000000..638d705fade86 --- /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 0000000000000..b9611bb683d44 --- /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 0000000000000..87839fb7c3482 --- /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 0000000000000..d2f64a05e7ce1 --- /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 0000000000000..e1e8018a21e35 --- /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 0000000000000..beded4faf714b --- /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 0000000000000..f4acb29809d68 --- /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 0000000000000..b98eef9efbd9f --- /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 0000000000000..1337239bf2dcc --- /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 0000000000000..be6a8ddfc9359 --- /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 0000000000000..5bda7ef8d3cba --- /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 0000000000000..8ca7fdd435fc4 --- /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 0000000000000..17d26a39c48f6 --- /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 0000000000000..9c837997b9a1f --- /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 f781daac15697..2b43135123080 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 45cde4c4f94cb..e51224dc593dc 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 70b9c4033a424..2b7e8910fb9da 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 3a04b411cb8e7..a87d773303447 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 92e601dd0c9e9..812349e96fce7 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 c5dbf017da8c9..a9d80181b58f7 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 da695201d6d76..1d36521d0b6f4 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 ce19e68fa1798..7b046cac3f13f 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 6601a104d9f7d..a8747a2bd43a5 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 38d47d3aa9cbb..0000000000000 --- 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 ce8aa4b961c23..0000000000000 --- 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 36c88451124ca..6901852a405fa 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 e9382f7092ae0..1296cf9878827 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 7234cc9fb54fe..0f7c9d9c31fa9 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 6da84d1991423..cfd1c04d0afbc 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 0000000000000..db4527ae31e43 --- /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 0000000000000..2e1bb0a61dbda --- /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 7591bf394d5c1..af0482f41b25a 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 78c310462f77e..de180b5970f3b 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 0000000000000..ebc896a480cb0 --- /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 0000000000000..37c29fa0b2d01 --- /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 ef5fe32a23dff..2d4482b94a9c6 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 6c83f853b2624..26e03d0163c8e 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 0000000000000..66e63e6950dd4 --- /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 827535d484588..75e15f8859e58 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 d2ddc6a1030a0..9f92c7d9398a6 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 36bc0c439a79e..4ba9eb630e53f 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 3680f8b63b0c9..0b78fb460ed85 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 9d084708e6529..3037d84180349 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 4a1f91719bca6..1d9d3cbf455f1 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 0b53557dbcd03..81ae0d5b40fd7 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 3f5bcb912ee44..8109bc31e07ad 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 13afc4c7889eb..4eecc36fe928a 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 c962e9fbf2d87..2a794285b52b7 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 a8aad06c999d0..8de4b3dc32a0c 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 3bb170937bafc..5b9d9d1bfe918 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 72680ef786e9e..dca999ab68902 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 9dcdc8a26af0e..fb872f775c5bb 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 36917706d719c..b22674d66db4c 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 5ca8ac3bcd9f7..65e82a2e4fbf3 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 e68de4418c9bf..aefe3d0b1c873 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 85350fb43f1f2..1c801341a0e99 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 c901631388f11..a84c733586ec0 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 b92ddadc32c08..fbe2672c17cbe 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 65f3a36cbe487..3daa29c02b107 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 177d5ffc06486..f5feab6f04557 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 1f58d4b72cea8..060b7dda22dea 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 44245f9b10e12..c10c7a6b63997 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 ad4678adcafc3..983ee667a2ef8 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 5b854979adfc1..8a61358d04521 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 e46201b1996c1..872113f1a51be 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 b4cfee637cb46..8ecabdac8c4c5 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 95b0a746db8ca..a5f650198cf22 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 2db687f514778..6bdd35ee642e5 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 282072dbb8dce..8d213e5b78075 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 a825bda9b90ee..ec8e05ceb9b9d 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 223127125e66d..52540169a4c8d 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 56e1f9fd62a08..c7918341da86e 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 0000000000000..293c1e992ac18 --- /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 aeba9605cb9a6..c938b0b2cc13f 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 0000000000000..b0e5416bbf63d --- /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 0000000000000..39264020f30a3 --- /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 6fc657d051594..708b12ceb7b4a 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 dae85d07685ae..149e386085d20 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 6ec620f535db7..974164265b50b 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 8630c7850298b..83b059b04f5e3 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 b9036ea4320af..cca2bb765e719 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 5a1dfdaa30252..1f09cfc38cf4c 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 f52b61794ce51..fcadce3f18b19 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 ad303966d046b..4bbacaa7bb1ad 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 a6acbb0d2e40e..28e2942c1f606 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 8990641cb524b..2b2c82c4f3728 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 0000000000000..e26e23e1e82db --- /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 0000000000000..5c34d4afce99e --- /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 b3acbf5f51a8a..e797d6812ed8d 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 443e0616cabe2..15c960c16f749 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 340131c14b6a1..96e989a9173e7 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 0000000000000..d1b6a2ce62519 --- /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 6d17b9c6e0920..6ab449873fc76 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 a8b96c617db58..9ba2c69885b2a 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 0ff9800716cfe..6d49e2e53cfba 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 a6d3455f91897..f76fcf41fa245 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 da12279a3ffa1..ec2d5385a0a43 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 b7b8c67a4280d..54c9e5a1ee54c 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 a240e8031cd68..4a190266458ec 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 31d31e6424177..e2186ddefa5fa 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 6491c7a8b0595..7a3f1f609a403 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 f2a59d6b22b2e..cdb0ea37a6417 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 f0cf88615047d..7d0f6463a4872 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 b29d41f183b73..f5192bf6cbe65 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 a193733aff26f..499f1c2e8454d 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 8923031ab6b87..b8d259bd6a682 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 2416e95c38f64..b71cc0276dc64 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 4a99889ad9cc3..59f836c10c03e 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 0b01d6a05b7e1..4f1d41cad2109 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 1560c20be5baa..9ce4797e50db9 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 2bb06b3a223be..08b7a2908f2e8 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 086a435a39fa9..4b04672615b7d 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 afdd9c5c18b33..d477c9c643a49 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 67175c86370d7..a23c29a5044f3 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 f15639661e5d0..7226a55854988 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 d046a9266cce5..00129ac1bcdd4 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 a59fb077dbdeb..fe8cc3f81eced 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 eb4ff6c1b0ecf..a147a6bdabc6b 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 6d12a3f5984ca..ebb957e54699a 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 f61bd762de458..a9c58b1302f56 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 0b735d6b0ede6..a5865abc46bbe 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 15c8dc06c473a..08f36661dde52 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 a94394527a61d..071b0147e19b2 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 9434ba4fba0c3..8cd3330052cf4 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 d8b1397edbd75..19d62bdd0682a 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 e601c6ee15ec7..f775b3607fade 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 842a00366945a..2f452a54927b9 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 0aba468174cff..73842073a542b 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 19c10bddbd7b1..c20e41067b010 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 143d845d074c4..7860bf15dc8e5 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 6df7f4b3f6de8..feec6431ee3cf 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 59ae5efcba191..d8dec2a486298 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 607166203e35f..d008421381b14 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 04f34ab50a133..232db750d5425 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 cf720be74143a..56477f0e6edf0 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 b415328a303d3..fa9e074899163 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 323d7d1f8b378..c2f76758c3d7b 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 9924413cb16bf..7b92e6e779fd5 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 dae156c8c8354..7050fcd3da346 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 462e68a097962..6ab87283e0b26 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 aee476723f1a9..cae8b00fb6d3d 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 72b1e00c1ed02..7c0c0136c3d09 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 07b284058fc7d..c60536961e01f 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 da082a1ff0d45..13f687e321e54 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 72755e74d858f..2438272503ac7 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 0000000000000..31df24c70a5d4 --- /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 0000000000000..62614b67ea69b --- /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 a76988506cad2..f3f9e5b59d3c4 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 0cec7c92c62b1..57e65664d5969 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 61d86c983fc6e..e64af66460ef4 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 d6277cd4983fc..b7d1a4907d8e0 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 7988a9883114e..b551cd8d39bf4 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 b6e398d269a6f..8cc4a7b13e687 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 d75e3ad07d9b8..ff78da6e63d1a 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 0000000000000..634bf27ba23ef --- /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 0000000000000..bfda349ac3a05 --- /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 f0e2d059a98a8..a2ba066db7d3f 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 0000000000000..e80db905d48e0 --- /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 dbc2017c95cf5..c6d63b35ac7be 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 5b6e39c153b89..193bc71d04d29 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 0000000000000..229074acde82b --- /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 7712c614adbea..302790cf6ae6d 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 1746d324d626f..9889bc8a6eada 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 0000000000000..c1bdb0e467c0d --- /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 9ad39990b9ffa..668ab79da691f 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 d8a5b4b32a101..941e1260894b4 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 0000000000000..6eda4b00499e1 --- /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 748f85db2843b..7ac8e4e3f9e78 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 c4893c7769651..4496e16cbc476 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 0000000000000..906566aee9f41 --- /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 1083e8f728ee1..b6c50a3b5dc3c 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 0000000000000..ca2bd6a996d67 --- /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 86f9408bef3f3..3257f3e969ec8 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 be923a9fdaa6f..fd0cee334cc50 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 7c97ff5b79bf9..746a2fcda1ba1 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 93d0a58b848df..3956dcafad705 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 2de75be2e50b0..afe9f8d677d35 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 9b0a6586e1c25..b842f89c8ac64 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 521d7aff8f976..50dce25679252 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 63eca247cca6f..51cd024f0b53e 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 5dd0045ab5d68..8659e12909763 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 9979e96261e7b..4f7cc3e57a975 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 9a960674e061e..fc09b860f705a 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 0000000000000..49761aa122844 --- /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 e262d3ecbfe45..b8bf2673ac3bd 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 0000000000000..b9db87b65e3cd --- /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 47b871196be03..88c91ab645776 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 d90d7ef6cdf68..9518ba6cc89ed 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 a7cd508401c6c..dd66369a37d3f 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 36428579a30e8..d4eb463e67051 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 8d49702b48154..391f54581f258 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 0000000000000..d8a836ea583a3 --- /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 5b2e66c66fe39..bad8554100790 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 0000000000000..3c8aba9149ea1 --- /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 6cadc094bb35f..494d6034f6669 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 9968838919513..edd0a7bc70b62 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 6696cf1e48b55..34740187d77d9 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 4211047878cca..7058b04b09053 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 0c23c8de616cf..2ae6b3149dc5f 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 05339e6473b6b..f331e62bd7016 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 127badffc826d..6d6c38f8dfc61 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 761c1db2094da..881d512159516 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 0000000000000..0a7a8a3990cdc --- /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 7f76210c2c6f0..95ec7e4dcfdc4 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 82051eef17663..6cf4381089226 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 2703653138fe0..b2c9bba61b98f 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 d938ae52642b7..6d3dbc6c3f4cd 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 6d7c6b4222d50..ff6621d64cbd1 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 8ee47f20515a1..3688f79c16689 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 6423694f76ec9..bee5fc0dbd1be 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 3c9eeaa63109d..208871f77022a 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 c054b42f51ac7..e06bcf99e3399 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 1646ec0f24ed5..ab6e82b301f01 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 4cc5792ce756b..01ffc9377d8b2 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 e4326439e574a..2a06f0c88b54f 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 a4b87110521d7..075869ab6fdc2 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 c693e1a170210..25966a1d9fc85 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 7c5e9314a153e..892df9b312e86 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 31a6b573ff2b3..a5d0447f79339 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 ffeeb069d1912..5f7b3a544db9d 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 ec0aeb081124e..54c8c61635f63 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 cf48aaee81fd0..f886d60696b8a 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 0000000000000..47ea33e443d22 --- /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 ded50870d7956..9b905b5a01074 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 ab47fb31fea54..b0f2efea40993 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 96ed68d32398d..0f7a5e0625216 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 d15fd7a501ea0..9fb4f2b13adb7 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 3e1a916085b40..a7aadfb61248a 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 6c875ca0c2333..fd4a320e417e1 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 05d1f7e1f51e8..8002605d93758 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 ccc4ada609d03..a0488094283d0 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 c764df4d6661d..e8661387e1e64 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 5e88831144b6b..7d445a4edffac 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 2ed80cb02c0d3..fdd0b1c931bd1 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 ce1e1939ef1bb..5bffe92e6d019 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 4e8358f3810fb..8226175786ae0 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 83e06db651e00..00397ea43e59a 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 8c8629002c93f..a5b13c083b278 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 0000000000000..d9ff1179f62a9 --- /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 84f90830a3f14..6aab2457c5278 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 50e0b0821ec81..e29ae10a60df8 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 5c6e96b4ce0be..38e7d2a667cd2 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 d8c8e4394f3a5..9e295496dd77c 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 12783d39e2711..8da37518fbede 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 6c5701a6593ee..39db06473c9a9 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 8c8e6288d474e..519222b4e3c10 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 ec6b04ae64fc8..4673fefbd9536 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 b34ce95297761..1d0cda70edea4 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 1662f6d0c7214..166078eb01dd2 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 57b5376c9fbb7..541f54b792c7b 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 bd031cf9b0274..55d38b00dec3d 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 4ab47954f51ca..224c9332fad62 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 0000000000000..8c7afa5d30fed --- /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 0000000000000..2b8b05aed89c3 --- /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 e79ef47502504..d0d4fa4aae825 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 3d481db8d63dc..134abb86b6893 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 5220f18380dd1..bddce3acbc847 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 3c3edf4e988ec..59db45aff0fa2 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 348dfebed1fcd..31731cecbeccb 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 0000000000000..074c3f60006c8 --- /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 b750b37aa51b5..3fad5f9309532 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 0000000000000..49e559c9f4c24 --- /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 0000000000000..6b2d59c824ab3 --- /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 638fb4e432412..a693de9b2fa4c 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 6a7d5b849c771..f466a7f8cf495 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 0000000000000..6acbc14a47352 --- /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 e96239f37cdfb..e1046b2dca6d7 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 66dbf74e6815b..f8dba47578d72 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 d559a0981ad69..e04738a962686 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 10b676be711b7..f2b5987d8cb1d 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 80e4d0d3743ce..2d5cfa91e1500 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 6d07d9111fc8a..446cb6114e97e 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 e23a4efa2f0a2..b824f6f20276f 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 2f52656c9fca9..01a4605f1651f 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 13273346241e5..132b824109e51 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 c38408c8f5417..5a77eb7155b86 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 ce38c82f08384..0bc5e9b14b29a 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 23a8772852e17..2d6f4076f6cf3 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 25da22f9be168..d35ff00058b99 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 9e593fa6c282a..c981a6a01e063 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 bd4f665bcd7fd..0ef1d5a887c21 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 cb9690ca3dc8d..cebe65017c984 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 d1b6a2ce62519..c4dea3334bc3c 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 da3a104f9ca32..ffd9b63271d5f 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 a29e976f12c46..b1b3ee8775dc2 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 ef674c1744a51..0cb95109df068 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 8f3c30a15e543..7058286f3d5b3 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 0000000000000..363a72c4c0310 --- /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 0000000000000..1859ab5a41d7f --- /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 9078782e36f0b..c2bd1f7dbedfa 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 35bfd4471233a..e2f6901b75c31 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 0000000000000..c164a18f6df43 --- /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 0000000000000..13f7ac9e97b09 --- /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 d786491e55a4e..0000000000000 --- 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 3c4cbbc0677be..f96d2b91ee0ef 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 4cb233ee0c480..25d7409036d8c 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 92f5c9ff33b0e..0829c1af193ed 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 3235ebbd9a8f9..1edc3d850f775 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 cea02893e849d..6944df380d3dd 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 519222b4e3c10..977d9d2be7d61 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 4673fefbd9536..629250c243cea 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 166078eb01dd2..e1993082b37bf 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 88061897abf76..c359bc9679e44 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 fa96da7ea6ace..a37fdcf5533c8 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 d3e97110b57ad..dfe1c6001cede 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 e1a1e60887172..4e9d9f0f021b0 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 3032b61d56333..3252ea21ee2df 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 200eed919407e..35c8b917853f9 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 9804f0d147868..59e4104c62478 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 bddce3acbc847..9763d09e20555 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 5e6795ba86ef0..f24c839ddb296 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 970f3baed7ab1..527e4bcd82535 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 5ba387128ef7e..92a663fab64d4 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 3b6eff3313077..a00a5d1fcd186 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 57dcd5631918c..c1e076eacd620 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 e16f16b7a87e9..f1509b323e098 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 a6c95405ccd5d..9a466f6971c0b 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 aae6e0430a7d8..75bbedc0b8513 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 e254dd8774a37..828b3bac4aa65 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 b5b612a9ed276..c6a8eb20143ea 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 05f1e6a960918..1623a75a621d1 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 bc813119342ef..d111c35722346 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 bb7321ede1b8e..0947891e5095f 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 9b48be3ad1bc8..4d129ae19746f 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 06727473771b3..4871d498a9bda 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 c7b6c7a6fe8e7..40078a4616e8e 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 dc06163a5f2c1..c89d8b206ecf1 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 1f3dfdbf39771..41b8348a3a26d 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 3b9948f88d17e..4762748e2618b 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 a17f33b5270c1..0d6caf180a3f6 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 0000000000000..4efbfe827c4bd --- /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 0000000000000..71732bfaf6f27 --- /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 47566ed1095d3..288595fa5f7a5 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 42b415630e92c..853ae6cebfb76 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 9db54b596f835..2b5f0a4a9563a 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 3745d6130c01f..b56abfcf316ae 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 ffd71c2d6af06..606cf82f10b31 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 134abb86b6893..2d02e0e710f77 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 f4ad9e4fb4a76..bb176babf9d2f 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 0440700c7ed8b..cb45519250a81 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 65008196c4b8f..d1ab12342dd83 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 17950f8c5e50e..a292d50cab895 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 5aeb9807b1eb3..3f66965dc98b6 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 c6b783298e3cd..4dcb01c3e93f9 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 b89c352cb506e..82073f1d5d60f 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 49fc204fe5591..6a58d46b34caa 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 480d07e7144f3..7bcda35a892f9 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 9a466f6971c0b..cd99577962aa4 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 f44103f70b8dd..b7e3f834781cc 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 594ef3d3ffd4c..db6ba390f67a7 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 a420b8d08e0b6..2b071ad9f7fbd 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 9739b5bc0fde4..8b41152496ec9 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 33393eeecdd75..568a219b952e7 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 0000000000000..feb9d58a23a32 --- /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 0000000000000..2d43262efc196 --- /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 90b2aa851fd52..f05441f3db1ff 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 017e25bb28850..f9b2a3fc928d2 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 c96b06886a306..b9fe8fafdfc08 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 0cb95109df068..f2273b168489b 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 ffd9b63271d5f..561f783e917dd 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 406e58e17d7a6..da5dfb4eccb5d 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 cebe65017c984..9df9f99c02adc 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 e53f8ed64b06b..41e22f2320ba7 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 294848246e7c8..0000000000000 --- 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 28bedd1ca6bc3..0000000000000 --- 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 9aefe1f8de780..0000000000000 --- 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 156e3814d8a1d..0000000000000 --- 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 5325765c8d06b..0000000000000 --- 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 59c601e6a2b6e..0000000000000 --- 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 2c2351b76ad4f..0000000000000 --- 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 f8390064732b9..0000000000000 --- 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 9142a430f963b..0000000000000 --- 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 9ab4e199439a4..0000000000000 --- 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 d891e7f2bab6b..0000000000000 --- 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 c7f0d8203833e..0000000000000 --- 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 24f5087ef7fe2..0000000000000 --- 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 c8b0c9050dbb9..0000000000000 --- 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 7d58bd3f35b32..0000000000000 --- 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 6a20db5bccdec..0000000000000 --- 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 20a262fef10fe..0000000000000 --- 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 13669c50953f9..0000000000000 --- 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 a2fb3fda206da..0000000000000 --- 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 70aaf89a059eb..0000000000000 --- 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 3e2b410024036..0000000000000 --- 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 9d53d70ad2abc..0000000000000 --- 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 092ae603117d9..0000000000000 --- 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 03e4ddaace093..6d6d6094870e2 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 99d8262f92aa9..2c9d1019b588f 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 328971313039a..5a2575c645415 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 69b288f7981bb..3cf71531614a5 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 22898daa92b21..ea1f53727997d 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 db11c3b12930e..652c5cdb38b6e 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 8d4638310d329..f8b63d7afe5fc 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 0000000000000..e425c5b94698d --- /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 e98a949971487..a15118031038b 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 bce93df47e941..28f61bb65c56f 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 673ca827c5302..824733a4f18fd 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 41e22f2320ba7..9947161017b8a 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 6d6d6094870e2..1a56456289f13 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 b3d7f10c2b7b5..1220c50456bb4 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 1c49665af081e..9f11f2c53c06e 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 80b34b47fdc9f..1cf2baf1df94f 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 8da53f6cbb280..3495e0104e852 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 e89fd0e7ed367..d68db98936249 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 a6de0eddd53d6..a1ca756a109b8 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 db20b98ed0f6a..9cd9f8e457d68 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 d46ff5aa181b5..c204e11c5f354 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 371251c3d2f6b..c46f1df7d58a0 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 48441c7541f20..058410350bba1 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 051acd0e75900..45354e97c4a87 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 a0952458e0f45..bdb2bfdfb57f6 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 e68be19ab7203..b6707b75f2054 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 dbd163dff3005..15ac5bbe96030 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 94a6853c57cce..9da2543d3f733 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 67f888cd10fab..66d95d63ab7c8 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 2d93e7b6a7ef6..a4273432acce6 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 885e264937e68..9232c9a652e8b 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 07fbe27b7c048..f708eefcfcfab 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 9d6e782717324..43ae9b642053f 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 604f24762a12b..f209b146be305 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 454aa521d5942..1d1919aa011f3 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 125f6303237f3..325517a508ef2 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 bd569dc580afc..08e02ccff050f 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 bb06789a9d338..79520620b1eb8 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 e862a2588c40d..5862b9b6a1092 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 247b776e53e30..d98fcbe787af6 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 594122e246d10..7670465e81315 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 7843f117d57e9..50c48bbe6aed2 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 2881eb78d6fbd..2232f402be5aa 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 fe964392680cd..ba449bf7a8e58 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 389500b91049c..9367e3045535b 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 35957ede2cc4f..959042fc63b91 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 63c9c3051d4e4..b1520fe7a33e6 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 d9ba036f7bbe6..d76f1607ad188 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 07f70de66a166..199872dc95041 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 4a9e44b189a79..0848e13dbed6b 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 6ab2af56de8a6..edd78a33faaa4 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 c21e6fc7a14bd..5ee6a5d63ba40 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 844946af12dba..3ee8e184d8ddc 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 6d0f630e84048..91f52a2f8c585 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 cf1334edf5db3..69da5e958b04e 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 31c161302239c..0dbb09172151c 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 337602bc8deb6..f743ff7a1df04 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 88767bde098f9..c9bad1151010f 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 bfb01ed547536..c373e6ced0e24 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 67fc800a393f5..8b17841c88af2 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 55e41dee84df0..beaaa9c75b73c 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 272f14fa331c1..98e645c40c3d2 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 883e69752d7c2..e5c0a4f72c361 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 2fd851509964a..6d49bbc381aef 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 dd3e3a7c1b9c4..7ab985cb8cdbf 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 ec3bd2846e1a8..8ac69b55c3af1 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 323af21664b16..192fbd7b5696e 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 ce8b70c802891..56c995e98b69a 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 44d11e482c899..278c1fa36331a 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 170818628b752..7a63d138d0df6 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 ba84f73e3531a..3f3b8bc6370c1 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 a1190ad13be1a..6c2bca0d28e61 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 e58dcecd23eb3..511984dd0fc87 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 be93903834285..a202ce1aa6a70 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 7084d5dd8614b..235658be3b78d 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 a3a2ffc66d724..6ac6cf2ecdeef 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 5acb5094dcbe3..da61befcf587a 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 d2657f3258452..314f463c007de 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 267549af75838..fe9883f2aaf7f 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 deb8f6162875b..a7c2c9ba6bb5b 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 3318c54d6b6f9..b9698bb6af3ae 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 ad5da6eb52715..92d86faa822d1 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 a566a62d1f846..edccd982c1d6c 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 5285ccf531912..be79bdd4eafdb 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 96c41a5268b4d..9d0b8a547f132 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 28ccaee3ae731..370ea6e08bea1 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 e2601319591a4..5b08cd3e6a2d5 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 1e71960980198..74a80905f7588 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 f55d67c1fc3dc..8c6373e6be889 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 89439f8a35a2a..54e66a6a92013 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 132c55a0f5320..58ed7474aecba 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 023dcb2b4bb36..ddebfb3149f6e 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 e491c482cb629..32a1ecee9b0ce 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 c4ba600af1dab..878d0e2231d85 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 bb77b10ad5c55..ba54f403fc48f 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 1aa6719c6e313..e9a21b335ee60 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 180b6a7699ad3..4afaf927cfd72 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 4b863396dbcf4..909e563b78ea9 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 01a492a721e05..ecd3bd9e30bcb 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 14b01e3c7be4a..48806f0bb59bf 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 a129e1b408e44..164b274ec16fc 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 dc390f25f0170..3096620dea812 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 741443fe91e35..7a21ab47808d9 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 40098db9d607f..3b57ffea66299 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 4d457a94dff83..07bb148844753 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 75ad6cf16351d..655da00aafaec 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 988bba727b23c..f3829af087d23 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 f308239b6d475..1e7cf2395ca91 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 0714ab8c48ebf..a51359f9ea878 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 1cd0b626f5510..d5c8ea17e5727 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 7777a057c2894..3cc06db199db2 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 b85fd73d4c901..9f792a77a0b9a 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 8937453ad90ef..6e92b8441660a 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 21d0c98603bd5..a23c727487684 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 5bf553a6b4e27..fa1fbe6a34483 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 84e37926b9d2e..a4ac2bbd587e5 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 08601a43abe02..87a27d7310d32 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 42e241da77343..954700546aaeb 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 5600e432ddde8..918cae2266e65 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 36b74b926858b..740cea27d59aa 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 53392790ff321..12a9ea7a3a692 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 4596828c8a7f7..2dd30f37d381a 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 8c56c35df8037..55cbc90dfb837 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 e369bc6cf9573..b38af087085f0 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 a02516d41e635..d4733df10ef90 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 4cf9fbbbd4890..107cc07cf9995 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 ed7cb4116ff68..cdb1bc362db1c 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 d6275075f4f2d..aecb098f12123 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 8b8b3352b3e03..26894b359f099 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 26b3493760d23..64f077cc7b79c 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 6aeec78a9de0b..f53cd8691aa37 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 cb3d85753a695..767eb3ca817be 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 3f5b097166b70..e1ccca466b84b 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 c3308a653104f..5c7e1685f69db 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 b77b28d64156f..14a8dab35c4f5 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 a4c4c5108d54e..791f954bd0d9e 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 6d190e7921922..b9893dd3939e3 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 adcb25e4e3b65..0243777cdfa7a 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 a2fc67402f23e..8c67ef4c56946 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 125a8ddb62eb2..e26596517937d 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 490c09706c8aa..4e6501e7630e1 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 8507ca2cb3903..b7f0d3997c26b 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 9aa393700f1cc..71ed7c7c9f481 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 64475b318c506..d92db48509a8f 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 3b16e74a4edd2..f3ea30a108937 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 19bafc1b112da..ffa295f6afcc9 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 2afd793f95c19..143dfc5595ee9 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 7e71e344bbf24..4b710a0c95c23 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 36cab5deb51a2..6a0168c3caa86 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 1a6af787887d5..a0256fed88e28 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 ca61b99d2dbab..8d278f7f7350a 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 177fc4c26f4ae..a8d558bdddca7 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 4200bb38465cc..e0cf65fe63663 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 b95726bae4f8c..e31cae82fd5e7 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 96baa43f4f803..7389a54ff640a 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 9d90489b193a2..e7174adca9cc4 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 dc43d1ef8ebe2..547a80c82224f 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 72d95cc2173bb..c561bed47f8e7 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 2604bdf1307f6..5aad0c7c3b156 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 a70c8ebdd2038..d3f87152a47c8 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 090d7dea7fc90..2cfd6a54f674d 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 062468ef28b45..f29660dd8fba2 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 13666c7455aa7..723f7e1143932 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 8f122bb2f056e..3ca19cffc1ccd 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 7bf289e5bff95..3f08c62fb8574 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 d5afd2459cb6a..cefe2f3a645f9 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 643fc21c88e99..226665842a30e 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 337c83d0c71ed..120508a0ac2a5 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 41b228a782728..5370ae2dcb6ae 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 23037163144c5..f51e8e7f1a3f8 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 13949e3052dc5..14f6c84f415b9 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 35d1ab22608d6..b88acaf398141 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 0145a71c0d7b2..860de97e5d96d 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 87346ec4fa5b7..c954e9385cc36 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 d9ba50274fda1..9a082a798c071 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 90e86fc55e65b..37eda7d25c36f 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 60f31535742b4..713c2df6ab9fb 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 302e26129c712..6a355709ff7dc 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 337f272c28fe5..c7e39b610a15e 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 8d4b519f59c14..5ccb082c7f3c1 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 196c31459d3f2..3731c861c52f9 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 730e06acc610b..d3730fb05f6c1 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 11c953906f0dc..47cfdb2ec87dc 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 a5ba2bcf8c3cc..7e01ae47831be 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 75f3667db69e4..0a0b87432a401 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 ace513c8f3fd6..6fcfe6a112b46 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 ee9a394184d4e..e96755a7ebb91 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 5333d41e14584..c9f8cc4bcd65c 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 4a89b92fff036..aa0acec92d661 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 14247d429667c..9c1fffaff6c0e 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 0e8f65ff9da07..ef59821d7e6d9 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 52483dfa4dc6c..404e9359c8628 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 857037bab1093..c09ca7102eb4d 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 b2767486e6592..1937ee65cde70 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 6afb7d61f7327..4028ed834f030 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 23ae70cfd0c9f..5573bad147e84 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 7a3a3d003792f..32e1362576a19 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 23db97bef04a9..afb1dc9ea18c9 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 f7574d68fb4aa..3a80448840003 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 fb970d77d9a9b..19c4e687936e5 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 71eb12db08bbc..b1e8550dc0273 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 d84f5c5c73c7e..8f50fcc62296e 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 93ab71cd6d0c2..7ab2b50c548ae 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 089cea7cbcd40..e97f95eff4443 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 ac8a36714f9c9..3d69cc729ab81 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 afa0e5688428d..a0d8731e24f03 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 fbecff8bedc44..9469f723448ae 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 56315c20f6063..e815933ba2051 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 ae5b78204d1b8..40dcd459d6ed5 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 0b3f8c2f078bc..9fe6c428e9c27 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 e2f35211ba038..bb9f16fa28ea8 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 c13d91d1c3d3b..81515bfaabe8c 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 6e430a5fa2611..cce8299d8de35 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 06e6a2ecbe278..2b1b6029e1a0c 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 f6aecda23d6f1..92dc8721b5102 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 5fac3e3216d8a..a310bc5e8b66e 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 1743916cfc825..5c4574ce110c4 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 f815aa153ef38..f9001dab53372 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 30a90ae7a976a..b055ae6ecd495 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 1b1bcdac498dd..9494f0a7234f7 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 d2a4f74edd929..9df6cb7a9a3c0 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 7fecf1916746c..91fd9f57cde41 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 794d64d7e64e9..e5df69dd076bc 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 f0d5725c883fa..ff37347c7b544 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 65edbdba1a628..02f3ff216b752 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 d9f583d515cfc..9a314c1cbe5c9 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 925ad46a92610..e041ac38d93f5 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 10165c0389dd6..afc677aa8d298 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 fed0b546122cd..f3d3e21b614c5 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 0732415264371..dcb2d58d071cb 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 5052cc57dc19e..9168266b9fe5b 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 79a90a07cb013..06607ed3de800 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 60c5375cd230d..1bc29e750eebe 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 34d1cab6fdcee..80a712558dee2 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 cc0de7274d49f..05d4b7554d8b9 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 59692fd76e326..0e054dd83877f 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 b29893225438d..a595d32b8f67a 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 a95ffcdf1e28b..ce61385b75eb4 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 5daa6d13cf6a3..72836a1b1acc8 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 e76afe4af60ff..172665b51e32a 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 0fde4b55f119e..50c07ff3dbab2 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 2644e4c3b5e71..16c8c03861af5 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 beefe799a31bf..08efbd7a5dd35 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 59951f466f831..33c1c7b945334 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 cce2805a4412c..26884ff008b49 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 db4ae2018ca5b..f35741e1918dc 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 28ee9c2cff91c..325ab1ce22656 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 136a0dd3d55f0..5cac179b6f440 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 eb5455dd7d830..35d5cdb8041f5 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 40b7ac766e87a..f2beb74c01798 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 57561b5cbc50f..35e5ab8d63dd0 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 d2c265790b9b4..1cad16a961c6f 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 2bf014a652c69..20aa4591f318d 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 c2c4c4d0337a8..c4d4b22dbc1cc 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 4049be82b4dfb..ca62e86803f78 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 306996d8dcc16..5dbcd32ab606b 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 e7387cd969eff..2bccca1609123 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 dbc89d69930c2..2c4d72e5408a2 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 943a7e8f6ee37..f418975a89b38 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 42d8da1b6627e..90afa17190a6d 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 dca53916d65b6..8eadcf4c53c58 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 6ba7fb075d16d..6dbc0da558923 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 2832f3e8dae4b..5a7827df403e2 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 9860f16923015..2fa5edd07842b 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 aff7a4c3270b2..8c9520301c8db 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 a162aa944dc67..3f2fafd3ccad6 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 875e36a1a9991..b0f261e4b345a 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 9a84263750a9f..073f49dc213cc 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 c7162db39b87c..47d6bc0a2bf35 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 8b0c2dce899c4..acf9ec1d78dfc 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 eff3e884b3bd7..deb819dcad483 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 3fdf23cd53c02..5f5e071a658e2 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 37bb135d5c280..5e16c33e60489 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 a5383cbc3b530..5a70951a8377f 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 ba7590ffbe159..2ba6473bb3e11 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 017f82899a837..949e367549876 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 49f9e90702310..0abea59173820 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 ebe0a2779fedf..22b48a2129619 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 15d8fcc4196ee..40f2ed946625b 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 a3eb896fea4c6..dfe673963d5dc 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 db43ecbf5d190..c56fabd189f08 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 3fa0a82da7e87..7818d52f7150e 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 90ed9b37626b4..51395791ed9c6 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 43dbe59c8b441..1ce3f1bcd172f 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 79e9918ff415a..e6864509b8e6e 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 4260459c9d064..65887938bbe94 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 d7da0dc87559b..73a844b9dd2eb 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 93b46261b29ac..9b5779b987113 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 73955118e002c..3e1d0b8ef67aa 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 e0d4fb5f40c7d..ade141a8e67ad 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 ce83347c99d76..281d8e89c4b28 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 aaee03632d3bd..323cb71fc1ce8 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 72c05e4c8e597..a7572422eaaee 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 5396d1d529cc3..06b5847eeb68d 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 ebeb4c6b525a9..6a6093117af84 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 af5b4f23845c2..9cbd40c50737a 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 6fbaa004f2aa1..b6ae546257f68 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 216b4ec105498..9a11ebfd2911b 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 86b17203dd3aa..802747de69729 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 ba2a281401304..a93276c45f99d 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 fc4bed4b1a001..a50227b43a566 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 d0c9c5ed9392b..b804e452681af 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 f6aa153d98fd1..7bead5768073f 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 967834391e6dc..fcb0ade735ac7 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 527b5039281e5..8004bc7d98cfd 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 b132757f0b152..93f5fa4810057 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 92be11cf2c6b6..de917d0bf65c2 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 579464a3146de..13cede26acb54 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 c89f5a58f576e..bf2f48c4e38bb 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 f7430ec4cffc9..2de8b2ede3627 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 770abdeea3c3d..ca958cb334346 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 f20bc874aa489..20b052f959e05 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 c88c99fdfa8e1..eeb46899ad7a5 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 ad038875cef83..9f235a661078e 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 008ba2f53e93c..376f2050fb0b5 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 7883d6366d4f3..1f900664e39bd 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 c7fe9875c57c6..86aed5cc5727a 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 bc834ee2ff41a..e54ef878191ac 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 1dd32b08c95c5..c95a9ba20dc35 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 a76ec2f91fad0..030465fcf407e 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 ffd690fb8d542..211cac4ef7147 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 6d4cee2cf48e5..e9d0d67bf11a7 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 bb0e1cfdac9b0..c0351e06afdc6 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 bbfa64010e3ba..97c994093713a 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 762df9d42c29c..d24ee424962fa 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 957ed8febfcae..bfccaa5ccd3b3 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 98103fbb8df50..be43b6e9eb1ee 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 ff85afae240ef..066efa8b1567d 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 9e427901caff1..9c8a14a8d3787 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 6900408be11c0..5fb427e1a3e3f 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 cd577edea97f4..ccf448ad72a09 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 cbe25e33be509..4b2be39e796ae 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 e2a850694866b..22ed8a073401e 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 e09f9577b2b03..6d1b97f05508e 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 a789dd3553362..9fc13211a68de 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 8af7864ea4939..1e146c132b103 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 cb45d6c5a4431..6546152741ab2 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 0de39481f8629..54098ff557a03 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 1652626d9f56f..0498b2db5769f 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 76f715bdb21c9..50822bc6a07fe 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 6e43b6db2c76b..cb4570fa27620 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 48955617613a9..6e309aabace46 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 8c8b8e8c9ef66..9789fa7e0829d 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 1f36b3105cdc8..2c4102b3e11a9 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 a726ebc34c5fb..a7fcc3b7e3d0e 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 74513f78d1f36..54f3c5582ac84 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 a5fb71bb58e91..bd17207c428c5 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 7cac92107a18c..3c5f70e4b5b68 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 616e1e5a07fc7..d1e758c309a44 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 afe72ce3daf47..5040b0aced97f 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 c2674d018305b..6159a05da3777 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 ac8837b6ca894..98d97f7736421 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 ba58d7518c6e4..1a117ccbf45c8 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 c580985bc8887..8694f142fc35c 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 1e938d796a4a7..f905ec86ea908 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 40d73b16b018a..efafbf4a6f6ea 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 ecf895a3e0f7a..0edc689af574f 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 9d61b29944ba9..78ddad2eb86f2 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 286139d6fe63f..6f458120aba1b 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 3a26281e749b6..dd24570ed202c 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 dff8ff4faf897..63cb7763de4a9 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 c9236042b14f0..5f6fc879c4139 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 d04909af54896..171c76855d8e0 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 03f4861574ec8..78f2c22a48ff3 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 312293e55cc62..2da7af5edaa25 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 e629a877e6a51..7e987845a7f6e 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 456808d926a82..5d518c6f38be8 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 8dc7f9e54649e..11d80f83e37be 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 15f259f2794d4..d64af3ea0899f 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 5c308f8c268e9..69b385c778d53 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 47f80ea4bfb32..b55f6e9cab541 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 e1d55dd7b8f5e..ee218b50a477e 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 29a07610f1e5c..e1fd0a2477294 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 9c8e4190bf491..f4305bd1a9f45 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 6bd52414173b9..fdb2d1e61b2f8 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 1e59aff6842ba..4770ea6d27907 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 02b72e1835c09..933ca6900c3b6 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 85ade27d7ba7e..186450bead666 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 98ff17ac35f74..0a6584f16c6da 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 696dc5d871335..b792174229db5 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 3a62678f11769..7f949fecc09fd 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 30f763ba4488f..43bcac0fd2464 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 f56b57fe0398c..12a60401eeebe 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 80abde5c72bc8..32e5ab2f192cd 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 8e620fcd48321..b61378c50bbaa 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 020d59da436aa..3f3b87205d761 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 27facd7cbc791..208db579bbef0 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 6b6af45f6d599..855cd38f3c4c1 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 68f0239219c7a..35e4aeabada7f 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 f9e3c5956fea5..d7e183c85606d 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 82043a2029661..acc4fe78bbe53 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 5b3a5638c74ef..5aec9e4ea7ca7 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 bebe8e757136a..acb7f297ddeb1 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 ba4d70200d714..ee0673e504768 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 eac1395483f26..a7e7d8c6ae0b6 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 ac07b7b6dec90..2bfeb944d13cb 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 27386a94c37aa..9887aca5925ce 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 c25eb47e0fbdc..61fcc96d1788c 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 492e3f940e990..8bdd2af90b27b 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 bd06921b3a740..93f00ba7ce5bd 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 32a53d10810cc..00a263cb6047c 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 1a0fe74391504..c5b69594c76e3 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 faaeaad6e7c4b..181e21f0ae85a 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 9892ae3945683..d34eeb693643a 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 d2862d4828d21..e68edfdc21029 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 8c22d419a997c..907fb00eb0054 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 eb856d91fcbba..bbe7f2164107a 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 4fbfd1b257443..84e43310e46c8 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 0ab84e42e3d9f..bf1073486fcfb 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 21994add4ed42..e165522e88590 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 102e46809b55e..858504853dd75 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 2b8f6d66e67ac..b9bdbafc213c9 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 bb790aec293c8..20821cef46e7a 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 17103bc8783ff..e7b8893848c93 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 e1b7a48948743..317ff4f773f23 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 2ae5d4161e15d..06f3a268c9ae5 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 29f38c2f1916b..7f24f525ae49f 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 fdf6e99f7280d..ba767658e8491 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 cf0c5372450e5..a980e0257e7e2 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 833e537b92ddf..917d7a06a0f47 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 2752696f24711..701bbba404c49 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 ce8119cfd0acc..4c3abebc8143f 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 364f094ccf7cb..f2d99539df19f 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 d2777a8e3ae68..73d5b32d077a9 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 61958c114c632..ed829a9326e9e 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 a059be6db3bfa..4ee70b9480d17 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 b556f960d6e24..1fda36f4ada36 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 7bc209b4b1a9f..caa99d98662c1 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 38d287754fa95..f01f6820b2687 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 e02daa7c88c40..e1b55ca9124b1 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 34280fac17e5e..bc012953fa0d1 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 ff6fd55bd5892..c6c5f216174ce 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 a2ea7a906fb7b..9f4158248d6bf 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 768ef135fe555..74cc38e4f4df0 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 1b54ea67554fa..07cc3bcd28c1b 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 cd99577962aa4..5a9287d6c768c 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 97c79647d32e1..a0262889187e7 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 0000000000000..66c5542f5647a --- /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 0000000000000..c7bcc0ba1cb4b --- /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 03f319b9cc97b..55811743e4d45 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 ee99a9966ab8a..ba933becda53a 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 06732f83f2af7..5fa33c8becfca 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 43da2bd760b3b..bc02fb3b205d6 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 0fe9bbede4153..71fad3639dc5c 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 40a473de30687..41383d4a0eb72 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 51ad895b56f0c..c259f8843263a 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 b99547db88ba4..9be9c1266c1c9 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 0000000000000..fae594e8414ce --- /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 0000000000000..cadfd2a68fa32 --- /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 0000000000000..13d758ed7a596 --- /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 0000000000000..330b47569b3e9 --- /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 00197a8719a6d..9ef5fbfd0a203 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 6024c4613f265..700d5d9d1255e 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 b9b4533b56e37..8841369749200 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 1d6b3f781f901..338f55ad754c2 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 1e8e2667c0aac..a921eaeae370b 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 352616d74cb3e..173c3b69ba761 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 a7f8d5849ccb3..0e8edc688c617 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 690f5d21c52a8..40424fec7ed11 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 7d685369e4d10..16bc2abe19306 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 7b7c57ff4f7f2..413e8905bea93 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 fb934f4aa4f2a..1ee0d5414b275 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 7b92e6e779fd5..0bc0ddb22d150 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 32486a8db3df5..9dcb7112f7ef0 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 2e238d4142f1d..dbe58b252a707 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 d510d57c52257..a55937999c4d6 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 17e9a25c656d0..c3a9f05fc7d9f 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 0000000000000..57117c9b1397c --- /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 0000000000000..63e3c2d548839 --- /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 0000000000000..cac9c2a7d0c2c --- /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 0000000000000..1d753bb4f1a26 --- /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 490a68922b176..7affdd066742f 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 0dc709e786c8b..16ae8372301ed 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 035faf8d22b00..7cf772ff7dd54 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 0d1d3b5b59256..37789a6ffa15e 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 3573fc65e5288..7ae16b9c6f05a 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 2cce918d4b798..94b187055e6dd 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 8098bb0efe02b..7476d43f773e8 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 bae83a71d3c27..ad829e45fccec 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 2d2fdf61a94b6..6260d2941956b 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 552142d3b190a..0000000000000 --- 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 092f8a326d9df..0000000000000 --- 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 0000000000000..a86e88d114e7f --- /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 0000000000000..b5505aab8c3b0 --- /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 15a63fec6d309..d7139e7bd1c34 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 0000000000000..9179a846066f1 --- /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 0000000000000..d037b9d1bd24c --- /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 0000000000000..c68269eb1b335 --- /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 0000000000000..4b25c722603c8 --- /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 72997ead35683..c781eff6d3272 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 81018230f4e07..2a99ae8afceb6 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 f5422c1f50085..4139e94610f08 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 ea68be542f42f..eb0d6df57b278 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 5e36fbb791e28..f9b8dd508d4a9 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 2edcbb5a829ea..69e76e18545c1 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 d331f2937e41d..ccd91253012b3 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 2df7b88f1607b..f33034dccb9c5 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 741a2cf761e8c..0000000000000 --- 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 8bf94c7f920ee..aa654a7c300d3 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 39a03139f30a4..90c8da120501e 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 6da13f89d0887..a9d808d56be93 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 8648169dfdb4a..d3a94bbcce96e 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 e6b73615c61b2..5776af2846688 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 0000000000000..050ecb4a3fe10 --- /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 0000000000000..66ae2456e2dcf --- /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 d284fe24052bc..bc298ef95eecf 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 467ff2ea16cf3..0000000000000 --- 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 0000000000000..a2f2520c9541b --- /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 0000000000000..64e85bc8c5d7e --- /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 0000000000000..724caf3c75243 --- /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 0000000000000..9548691e49ec5 --- /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 0cd77b95b7b1a..c695a2c4ebe84 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 6ea779c28be29..c0b46cd1b44b0 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 0000000000000..1e268b953ef09 --- /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 0000000000000..94ec2cf2726cd --- /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 0000000000000..a2b896781739c --- /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 0000000000000..56d66781d187d --- /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 0000000000000..0edf3e67f3c03 --- /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 0000000000000..9252945c8f552 --- /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 0000000000000..c867eda97389f --- /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 0000000000000..846417c8cd021 --- /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 5076b1649635e..ec87259c90a58 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 4ad5c0e5f038a..08add53bafcb1 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 f1dde44d05aab..4026980ae1c89 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 447dcfcdda6ee..1e40c23a26d4d 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 3310a4e1c893c..a468db60a023e 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 6bc42b1980c20..99c4bcfb0d50f 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 acea79493c0be..dbad4c02ee5dc 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 0000000000000..32966e72c2eec --- /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 0000000000000..a6f5c5a387c17 --- /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 0000000000000..d7cf25dca3239 --- /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 0000000000000..d31d18ec79367 --- /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 0000000000000..71fcb871adf42 --- /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 0000000000000..72b20f769575b --- /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 0000000000000..580534e5668c2 --- /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 0000000000000..371af7299b3ea --- /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 e864d292c61cb..3a3aa1fa788ee 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 bc7cfffbcf7a3..c91ce0e6aa89c 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 0000000000000..83bd913e3eedb --- /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 c6a64c51629af..0000000000000 --- 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 db3de2eeb67e7..c17d09a4bf7dc 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 e0b4e1e88daa0..b95a378a35a5b 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 bd8c619edfd04..41596a257dc9e 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 266ef8811955d..8315f41725ed0 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 e92df3f388e97..07765dbf601d4 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 9cd711d313a54..a3604b31cf75d 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 9ea7e492c7893..82e59dc7b3ad3 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 f492ac74dcaa3..c3b643df2ec45 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 db11ca497b515..71de0fe1e6ab8 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 56088c953ef08..0027758505fff 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 c677a7613e3e6..4a2bbe9be6367 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 bade9615b630d..44e0ad166353c 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 a7aadfb61248a..01bbf59adb16f 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 fd4a320e417e1..f6dbbfc735890 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 8002605d93758..60c556135b465 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 0000000000000..1ad6c18fea3bf --- /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 0000000000000..0b2f092899a6f --- /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 0000000000000..ae21c61a8fad2 --- /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 0000000000000..5aafc82c29e0e --- /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 b9355574e0806..7b281208f79e8 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 a1035168d8e87..3731bb3994e9e 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 0000000000000..f46454e45eb82 --- /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 0000000000000..ff5cdf9c5fee1 --- /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 0000000000000..c2d4374c5a4f6 --- /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 0000000000000..ac3a2fe490e40 --- /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 0000000000000..6fc82551818ce --- /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 0000000000000..4c8e5a36e4e0f --- /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 0000000000000..08ca206671de0 --- /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 0000000000000..0d6bf900f528a --- /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 0000000000000..3e56bd816b0a8 --- /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 0000000000000..819936ff53904 --- /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 bb5e2bfb324c2..8ca63956f6b79 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 6ce6e677b5a26..6a983fbd5587f 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 5b41c1e1a653c..b2f7d20bf261c 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 66803c3e87b10..14532ecfd5079 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 dbb9585dbe27c..a321a0d118cf4 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 687296a27c13f..d07a271bfc01c 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 9403d6d56e486..16e7a77366c7d 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 9eb7554fabeba..ef4a30c1aa012 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 0000000000000..95d3eabc97c36 --- /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 f14fa5a4ad634..ae653df104b51 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 ae5915a032b8e..c00885de6b967 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 408339f5a10a6..6e50cdfe3ba9a 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 0000000000000..b24a6d1a32cb7 --- /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 14f1403ad536d..321a7efbfc5e3 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 0000000000000..315ed3d58520a --- /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 f2579031dbad9..fefbd0363d449 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 d317b09d4d305..ffe3aad05b0eb 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 6c5a9b7c36c50..fcc9e89da4796 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 58f8544174044..e3214eab3ec47 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 c5d1cc921dda6..4d645a9d2066b 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 0000000000000..e25068be8b13a --- /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 220f0bd8e941a..34f4d09877e3a 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 fbf5dc5c5af4b..f36067923e1b7 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 29445ac8e4715..fba9556b5f4ea 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 9b708e0d464d2..f36c7cc69977b 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 73c15c864b2af..6a0dae8d3deaf 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 0e9f4bd953c2a..2299cd2fed344 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 75fb48a5becd3..c0ae46bf18c4f 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 04f59707ea634..5035071a1f2a1 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 f54a782ea1334..b4d9c5282d678 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 8e83f123a8fa2..5dd5477cae2c2 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 01bbf59adb16f..c10ded1c3e623 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 f6dbbfc735890..a6a6a929da9dd 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 60c556135b465..bd0b538fd94dd 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 da6d245f456a6..173d295c079c2 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 2d02e0e710f77..6cd6f373c1104 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 159c0d600308f..3f5113b3ac44f 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 e9f37c232eeaa..1cf9a54210973 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 4751d3ca29863..c6f484e8f1697 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 50ee1cd1d262a..ac2205205ab46 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 2495f63c7614f..dfa513085019d 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 2447ab1438ba4..d73c169fd647a 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 4b4d051607b8d..b38cc2925dfb1 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 34fa5b7af55ca..c3bee2d758df0 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 3915c6600baaa..63b13d8ff7fd3 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 98efc91cfc34c..e360f615ad369 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 573701ae9a6fb..9f88e2c391b3d 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 57117c9b1397c..f7796f8ef4c5c 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 eb651d8aedd12..57611fcdf2484 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 43494fea6992a..0000000000000 --- 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 c77a254be2f10..9b3f86070a6cb 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 58a471b4e7246..aa25bf2c8eb3d 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 4fa5cdcb7c9f7..9100b7ffa03ab 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 631b916202505..bbe91f77a7204 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 5b16462300446..b9e77a3a5f273 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 25f78cce55611..0000000000000 --- 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 55651e2f81165..a99bc950ca445 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 4ef918aab09e4..957b33618d9cf 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 dcd50215c6a85..4aaaeee5b672c 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 ebba6a0e89a69..89a1ac5d34a1d 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 d212c1f2cead0..32a81de9f307a 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 ded149f0b6236..0939535a87135 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 388e65385e7dd..a5795ae321478 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 fa04d6e4f6465..2dcce23ab2a20 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 a87cbfe5ab4d3..7834011afa69a 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 41b21df2e83e1..1b2ec3d64b087 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 d842a0650b423..006a5074f7c1b 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 501d0e678f0f4..1829d46e17232 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 f8444ab6e5879..8f3c84564787c 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 0c9250dcd16f7..4267b6465b179 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 31a5ed02429d5..3cf1d8500e12d 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 e40848ab9f47b..5a100aa8a404d 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 8f405700fa2c1..a278997ecdf73 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 d7f60b2396cd0..99715ab6998d6 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 39c33e6486f69..f5c721221c328 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 831ca790e57a6..731dea453058d 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 b9b12aeab0754..305c3ed2d88a4 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 7bae1e51f1ab3..c9f33c2f23711 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 1be9873d25c4f..bf8802c39f9f8 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 52cf6b988f1a1..dde70238377a7 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 23154492c9f44..5be39b4f082dc 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 56978f03123a8..8f432305f2ba9 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 e3cdf7e8bbce8..3fd41b8a06fd0 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 243f1df257a4f..6467768f75e28 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 bbd7553d1fa33..81d6aabf38165 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 9fd2cfe6eab0b..d623ea664bc53 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 43ba70cc100a1..53c5fec2bd5bf 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 0416a0124627a..80a5474ae41b2 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 4effd2ed23d7c..51b3a198667b0 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 4baa9fd877f10..b7169d3aedc54 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 a77a2e443b9d5..11bb01d3ca7bb 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 1efab79996388..c7a5c43b05c05 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 7724b5fe334b6..7537e310bff22 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 06890c0b6fd59..e93af3051d451 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 fe2f9c8cd2cf8..8b735b51d1e68 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 8c14a203f7800..3610b240572aa 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 5156ed7f05478..534850d2cc927 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 75d80b8599031..dee5dce49076d 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 6991c66e8eede..60f0e09875dbc 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 3e37fc871405f..e377b3c0db995 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 5f4f80061ed2f..5bab490b303a2 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 b38a7ef3052c2..48ffb06ed3bf2 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 e9b9749b659e2..5d1d3e6e62b54 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 d25b17cc0dc6b..737efa4634de2 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 c582c929c67cb..5aeb0e7db72a4 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 8313ec635c69a..80865880cd6c4 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 2999b2f68c29e..a93ac5420a785 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 49160f9b5caf2..faa160063dfa1 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 4765f52b855d3..22e8e12c66817 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 05f63f5ac05af..36b0e30f92efd 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 ca2cb0c3d20a7..762722a77be79 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 c9c95b2e99bbc..ffd6d43bec959 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 898f12ceaeffb..c8b21729484bc 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 37bd72ff71c59..0af23ab0dc736 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 fe0034c23e0ba..632e17c37509a 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 c990a7c632caa..926724156d553 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 ef091dc83a429..d4d843e8cc663 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 fd775ec9af2a9..039a4f0f548b0 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 0c0696f801a95..a2a44e7d086da 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 509d70caf5291..087ec58e83806 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 350830abcbba3..7215dd933c87e 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 86ec7431bd801..9160732e32b3e 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 f8092475f1ba0..302392674ccdd 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 015fd3a501621..385449d8754b6 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 9a5903a278fb7..e26f1375984b5 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 8512cc50dad29..9b65a2b33f752 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 323c46a6cbbda..4552d3912f842 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 0000000000000..376adee67bb36 --- /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 0000000000000..24d728bd5c189 --- /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 0000000000000..65b40d9a924ea --- /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 1f5e39c532a6f..64910663ac5cf 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 d12fce4efcb95..79c99d62e2ff6 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 0000000000000..d22237be1fdf5 --- /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 23b3da831ddac..2b8d21f8f0ac1 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 e8533e0561cce..c33cbdd77232c 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 29e9bfa4cf224..e477d7237c273 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 7d9dc9d406035..213ec6d8f23ce 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 ed50d78f4de3c..c8eefbdd92c6e 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 58b66bb74b5e3..fe803b76364d8 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 44c281560fd54..94c869bb54a1c 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 87d0eca815cd8..cac21f9732904 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 0bdda65b32c9d..cdf4af1746e5c 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 0000000000000..70b448a80dc33 --- /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 0863d10fe0c10..b59ddcc424ff8 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 6f0a605fa0e14..c0246168671f0 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 0000000000000..8ae6e6bd25607 --- /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 dc987421e2661..ac5af32203c91 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 c0fe3dc497025..210b201ec4c68 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 aa819007001a2..456aa47aeab40 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 26a25886ac866..27a1d9db7739d 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 a87888ed85c93..d250f5be388d9 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 abacffe4a46a9..3692b19f7e440 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 4c29c4284860d..c46a4973e2457 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 35c05316465f8..261a2a6e7afb2 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 a70b6b93de5dd..a0fee65518fa8 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 0000000000000..03d5b4333cff4 --- /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 0000000000000..aebf85440dfe4 --- /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 0000000000000..cfc9907424f62 --- /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 0000000000000..d0be3ff2e77fe --- /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 0000000000000..c7251bb78518c --- /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 0000000000000..8dfab23f97887 --- /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 0000000000000..adb77f7b9d2ea --- /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 0000000000000..30b73d397b674 --- /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 0000000000000..3ff823a09cb5d --- /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 0000000000000..2f73df3596212 --- /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 0000000000000..17c571ac7ed39 --- /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 0000000000000..07dd57964a13e --- /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 0000000000000..3dde3bdddac67 --- /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 0000000000000..24d0b9015aa74 --- /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 0000000000000..517a0cea4cce7 --- /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 0000000000000..dbbc81824a479 --- /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 0000000000000..0f430ca87aaac --- /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 131b445017353..731396014d835 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 05e22b035614d..e853e6b77e8e1 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 dd106607353f2..a0e36688a2f8b 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 2b5dbf4999af1..4a921c3a1d177 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 1f879ebcae9a8..052e0ab7b32c8 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 ef6f09f679de2..c0848f630daa8 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 7437bf5fd4ece..41060aaecb3df 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 c37e050b0823a..84a12d8c63200 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 9b6bb6707ab49..54343ec245efe 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 6200af754507a..15f5295e5ee36 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 39980f03e3cbe..a4df4d0f1a76e 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 ecfbb388081ba..8a6396d993973 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 f67801dd37730..4f8937baf8fdf 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 3189e7cf32d08..246fc87114db4 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 5dffd3798399d..395304c48a914 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 0000000000000..419e4f04d74ae --- /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 77a56eadee526..3f95b6adf6b45 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 3fbf7222d1529..de9598b52087e 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 30f3fad82dafc..9aa05f64754cd 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 fadf1767b1db6..b9e95a2ee837e 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 385449d8754b6..c1c18c4c3cd3c 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 a1fcefceadfb5..3cf7acdef93fb 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 f3808984137df..b3aa4714fa664 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 bb05a23feb174..2ab2795e138bd 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 f9b2a3fc928d2..017e25bb28850 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 9ae820cfea4e7..d8ef7e1106c0b 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 7c7f7dd28f6ca..1088ba196840c 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 752dc8b338661..3bbf94cd0722a 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 2ff43a854da23..e9bafade964b7 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 8c951b4d5d1fc..ef15d14750f9e 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 26c26afe8f545..a3799588b19f1 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 1a929df039ec0..f76b6b903fe95 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 81b47735d8fe2..84c8f8b5a3fe1 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 ffa8cb533bc5e..d32323d4d0b23 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 40bbe9a89c992..5543e0071b4d0 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 e7b4067881656..91b2ae8d3ada6 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 be94e69f74f9d..ff9c6d47660fd 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 c63a8f82f1704..88e819bb7f9a7 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 23cae0ee852ca..fe80db37ee36c 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 0000000000000..4a219e23aff09 --- /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 9ffdd3070e43a..48ca3852e715d 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 3b82ee6ef0f1c..065e3da189999 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 c5fa5ccc89957..04eb67e792163 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 2b071ad9f7fbd..ae1916158f85e 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 3692b19f7e440..32601f4590558 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 145b9ec56a344..9d6687a771f36 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 46186479bf726..08e609938938c 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 e12fbf2918302..5c934b0d2e040 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 00800b9474716..69e31522ef40a 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 57d812645ed38..65c55f356c44b 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 c3fbec8a6d7b3..bf6583a6855f0 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 bac55c8510929..0a337eb28bc1c 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 794ef71bf0536..0000000000000 --- 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 8026d99713214..0000000000000 --- 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 b164ab9b44e4f..0000000000000 --- 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 0a5d5170473fb..6b0051f12bc29 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 69aa2a4502bc0..e445e5b935af2 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 f2e78eeee99ef..63754adc5e7c8 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 ccd0eb5c80fe6..f949e927ec095 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 c5009138b4078..6e76de5aa420d 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 2df4cb712ddd2..9dfd5b1efed7c 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 21db7e52e4f8d..84f693a529a68 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 4183f217a61fe..42e50db79294a 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 31bdfb398c18a..4fea86a2e3395 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 d5008c87f3b6d..e044c8fdfd1ca 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 30be45f5eb163..204d78f5fe7d2 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 6c7d5d581ce61..d3cdcd82b4989 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 db88284bc8881..5609eed4c0801 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 4d4bda5e6b4e0..c7e49ac77e7be 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 49c1ba045d5e6..1b9dcb5da28fd 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 19447dec2b4a8..dc7209b9f1c98 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 f44e72f5cd50a..647c4dddb2bb1 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 1db5c784660fc..4f5cfdcd3ba56 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 cc33c2ebff447..1491829b33999 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 da28e867bc976..b1036e1f8b682 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 c845c0d343261..56afa355b0482 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 0d6cf9905d4a2..1fe2f2adecc79 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 45dd0bfd5d477..c96537bfd0813 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 dbf94965278d6..56b5ab66773bb 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 5f863c0e62b9b..8d8a34bba8b79 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 468cbdfa23aa5..4f8b24e623ac3 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 9b633b0baed7f..407a66086805f 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 9df9f99c02adc..89f74e669e9cf 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 9947161017b8a..c8c1aa501b981 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 ed0e154552caa..c0c66e81db26d 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 220a336915bf1..3b71823ee6bde 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 0000000000000..7a92b84ac36bd --- /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 848a10efed668..0000000000000 --- 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 be9acfd38ab0c..2ee2f4f019b12 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 2cc7595ce6731..8adaad0b71c63 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 37182e328ebf3..692926d3049ca 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 48367848ed48f..93daa0bc7ed2a 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 86316fe7ef8c8..9736a695e81c7 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 0000000000000..b625b3051f15a --- /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 766aaf6df36ad..0000000000000 --- 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 0000000000000..a6d98df28c413 --- /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 8ca8bdfd79a49..0000000000000 --- 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 0000000000000..b625b3051f15a --- /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 766aaf6df36ad..0000000000000 --- 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 0000000000000..e2d5ffd3ffdac --- /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 b36d0c513116c..0000000000000 --- 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 d0361f4550576..7cc16fe654268 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 0000000000000..862b4a916bead --- /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 5df26a922d7c3..0000000000000 --- 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 65975f65af24f..9278edfcc6ddd 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 cbb5b10c48aaf..548ac5dc3eb13 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 8d0e928f72770..fdda0a2316779 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 4eac1baa43d79..f9cacf100b691 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 44f1fa63d732b..5124e8d5c0685 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 92a934f2dd674..987bcdbe27193 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 0000000000000..540485920c2ff --- /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 90b6cdb52e3c1..0000000000000 --- 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 1af856fcdf616..ebbe810a6629c 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 79e202046a4e0..08dc0f949e01c 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 c165cb552b9ba..5ab9d032c55f2 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 1a56456289f13..ca0826165cf2a 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 78831e1615004..d047ec9ba36d7 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 9c22ecd8572ef..ca9a415c4c958 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 b998fa5d10db2..58494595ad2e4 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 b023aff4b9e08..ce6e443a25025 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 540ad2b2db69e..9a17f7fe84f4d 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 43dde2580b66d..05b6c6244810f 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 adbce777a4942..0c7f09c56f36f 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 5ec4e6f0ddf37..46f566eb27e2e 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 3a80faa90c501..88e4be9eb93a3 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 55c0b7f16e14a..908584a7be03e 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 832c4322a2866..12b958fa3c67d 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 c2c0412d940c5..0000000000000 --- 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 9f4158248d6bf..0000000000000 --- 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 908584a7be03e..60c98bd5cc1c9 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 3571ffca63b07..59deaae59f450 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 0000000000000..cefa99722fa3e --- /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 0c6611acb77e0..664abac92db93 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 e7f21716541cc..f383778b764d2 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 ab01467e75cee..47b4840665e64 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 0000000000000..70854e31f6956 --- /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 0000000000000..d56dd6a02d4cd --- /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 0000000000000..2d012832f1ae2 --- /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 32601f4590558..3f70a57708b46 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 f2476f7516611..1244e179f7f6a 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 c10ded1c3e623..92e1e27c90041 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 a6a6a929da9dd..30b6982a95d39 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 bd0b538fd94dd..8ecac17ffa0a3 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 89f74e669e9cf..dbc10f3a6c41e 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 c8c1aa501b981..4fa23bdb9ef47 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 b898faee5fb07..18c2202fb8d2c 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 0000000000000..4ca5c1a1cf2af --- /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 0000000000000..8412844a911df --- /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 0000000000000..35678cd2a19fd --- /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 0000000000000..80df7f644eab5 --- /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 0000000000000..552de143ce1de --- /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 0000000000000..58262f9a7aaeb --- /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 7b4fd29011b9b..e8a61de40bea2 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 f86903f3c185f..ec5f45930ce22 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 0000000000000..d0bb30144b7db --- /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 5a4b2b5907ea2..c3ebd9923e2a8 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 0000000000000..2249e2ee93761 --- /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 0000000000000..42c29b72766b9 --- /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 0000000000000..5ae368e814c43 --- /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 594f9975d29fb..68289764ac3e8 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 0000000000000..f797f04d42061 --- /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 0000000000000..074993f2bd62b --- /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 0000000000000..486f6445a8b24 --- /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 04a4eefa0d25f..fb5a3b54ad591 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 0000000000000..7afedc3d90fcf --- /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 0000000000000..26b4c7aca3a67 --- /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 e7f9e7d3c3b81..fdd36c76f6e4d 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 1b87498496b24..04074fb2b10b4 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 2b378b02554cb..f5b0c017dcd18 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 cf3a9e6405f69..47ea6dd2ec164 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 9eba054ab5302..e5c137a6d5db4 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 0000000000000..06f79f0f1afc1 --- /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 ca0826165cf2a..31c3399f9a387 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 41406bb6c9dc1..1938d8be4acd3 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 bd3fc05c6d8f7..e48483785490a 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 14d67807a86af..0854488d5f29e 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 4c7f6c0a2750e..43b08ed0787e2 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 9c1be8628c823..048da6cbabeb3 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 7d0f6463a4872..55f9ce0da063c 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 cf525f59e9448..f5525820da6dc 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 1f33f44a20d6a..984b6bbb832f9 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 dbc10f3a6c41e..89f74e669e9cf 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 4fa23bdb9ef47..c8c1aa501b981 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 18c2202fb8d2c..b898faee5fb07 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 4ca5c1a1cf2af..0000000000000 --- 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 8412844a911df..0000000000000 --- 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 35678cd2a19fd..0000000000000 --- 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 80df7f644eab5..0000000000000 --- 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 552de143ce1de..0000000000000 --- 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 58262f9a7aaeb..0000000000000 --- 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 d0bb30144b7db..0000000000000 --- 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 2249e2ee93761..0000000000000 --- 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 42c29b72766b9..0000000000000 --- 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 5ae368e814c43..0000000000000 --- 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 f797f04d42061..0000000000000 --- 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 074993f2bd62b..0000000000000 --- 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 486f6445a8b24..0000000000000 --- 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 7afedc3d90fcf..0000000000000 --- 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 26b4c7aca3a67..0000000000000 --- 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 fdd36c76f6e4d..e7f9e7d3c3b81 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 04074fb2b10b4..1b87498496b24 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 fb5a3b54ad591..04a4eefa0d25f 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 e8a61de40bea2..7b4fd29011b9b 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 ec5f45930ce22..f86903f3c185f 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 68289764ac3e8..594f9975d29fb 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 c3ebd9923e2a8..5a4b2b5907ea2 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 f5b0c017dcd18..2b378b02554cb 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 47ea6dd2ec164..cf3a9e6405f69 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 e5c137a6d5db4..9eba054ab5302 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 06f79f0f1afc1..0000000000000 --- 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 31c3399f9a387..ca0826165cf2a 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 e80e8c210c7c9..4bf39a8bf1d79 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 a229693ed9f20..bd9c549eb0f40 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 deee988052ef2..8433dbb2fbf87 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 266c0185745af..6acd2e4db8f94 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 3b635796edd64..de0d2458a5cfa 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 0639fda39ca4d..a5532e176b3c3 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 ? ( - - ) : ( -