From 5529c96dc67411a6f8f9767924ef55ce6b590a62 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Thu, 9 Feb 2023 08:27:00 +0100 Subject: [PATCH 001/203] [Advanced Settings UI] Add support for global settings (#148975) ## Summary This PR adds global settings to the Advanced Settings UI. Global settings are displayed in a tab next to the UI Space settings. The search has been changed to search both tabs at the time. The badge next to the tab shows the number of results in each tab. Everything else works as previously. No search: Screenshot 2023-01-18 at 13 01 39 With search: Screenshot 2023-01-18 at 13 01 56 Although there are no global settings as such yet, I've moved the telemetry setting to be under "Global Settings". Screenshot 2023-01-18 at 13 03 15 I am not planning on merging this until after 8.7 FF though. And will add Custom Branding settings right after this. ### Checklist Delete any items that are not applicable to this PR. - [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [X] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [X] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [X] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) ~- [] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ - [X] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [X] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Vadim Kibana <82822460+vadimkibana@users.noreply.github.com> --- .../management_app/advanced_settings.tsx | 276 +++----------- .../public/management_app/i18n_texts.ts | 35 ++ .../mount_management_section.tsx | 9 +- ...ed_settings.test.tsx => settings.test.tsx} | 55 +-- .../public/management_app/settings.tsx | 346 ++++++++++++++++++ .../management_app/settings_helper.test.ts | 153 ++++++++ .../public/management_app/settings_helper.ts | 56 +++ src/plugins/advanced_settings/tsconfig.json | 7 + src/plugins/kibana_react/public/index.ts | 7 +- .../ui_settings/use_ui_setting.test.tsx | 63 +++- .../public/ui_settings/use_ui_setting.ts | 55 +++ .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 14 files changed, 797 insertions(+), 268 deletions(-) create mode 100644 src/plugins/advanced_settings/public/management_app/i18n_texts.ts rename src/plugins/advanced_settings/public/management_app/{advanced_settings.test.tsx => settings.test.tsx} (89%) create mode 100644 src/plugins/advanced_settings/public/management_app/settings.tsx create mode 100644 src/plugins/advanced_settings/public/management_app/settings_helper.test.ts create mode 100644 src/plugins/advanced_settings/public/management_app/settings_helper.ts diff --git a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx index 9aeb0d10093ba..99f5f031ad4b1 100644 --- a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx +++ b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx @@ -7,283 +7,91 @@ */ import React, { Component } from 'react'; -import { Subscription } from 'rxjs'; -import { UnregisterCallback } from 'history'; -import { parse } from 'query-string'; import { UiCounterMetricType } from '@kbn/analytics'; -import { EuiFlexGroup, EuiFlexItem, EuiSpacer, Query } from '@elastic/eui'; -import { - IUiSettingsClient, - DocLinksStart, - ToastsStart, - ScopedHistory, - ThemeServiceStart, -} from '@kbn/core/public'; -import { url } from '@kbn/kibana-utils-plugin/public'; +import { DocLinksStart, ToastsStart, ThemeServiceStart } from '@kbn/core/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { CallOuts } from './components/call_outs'; -import { Search } from './components/search'; -import { Form } from './components/form'; +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; +import { IUiSettingsClient, SettingsStart } from '@kbn/core-ui-settings-browser'; import { AdvancedSettingsVoiceAnnouncement } from './components/advanced_settings_voice_announcement'; -import { ComponentRegistry } from '..'; - -import { getAriaName, toEditableConfig, fieldSorter, DEFAULT_CATEGORY } from './lib'; +import { Form } from './components/form'; import { FieldSetting, SettingsChanges } from './types'; -import { parseErrorMsg } from './components/search/search'; export const QUERY = 'query'; interface AdvancedSettingsProps { - history: ScopedHistory; enableSaving: boolean; - uiSettings: IUiSettingsClient; + settingsService: SettingsStart; + /** TODO: remove once use_ui_setting is changed to use the settings service + * https://github.com/elastic/kibana/issues/149347 */ + uiSettingsClient: IUiSettingsClient; docLinks: DocLinksStart['links']; toasts: ToastsStart; theme: ThemeServiceStart['theme$']; - componentRegistry: ComponentRegistry['start']; trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; -} - -interface AdvancedSettingsState { - footerQueryMatched: boolean; - query: Query; - filteredSettings: Record; + groupedSettings: GroupedSettings; + categoryCounts: Record; + categories: string[]; + visibleSettings: Record; + noResults: boolean; + clearQuery: () => void; + queryText: string; + callOutTitle: string; + callOutSubtitle: string; } type GroupedSettings = Record; -export class AdvancedSettings extends Component { - private settings: FieldSetting[]; - private groupedSettings: GroupedSettings; - private categoryCounts: Record; - private categories: string[] = []; - private uiSettingsSubscription?: Subscription; - private unregister: UnregisterCallback; - +export class AdvancedSettings extends Component { constructor(props: AdvancedSettingsProps) { super(props); - - this.settings = this.initSettings(this.props.uiSettings); - this.groupedSettings = this.initGroupedSettings(this.settings); - this.categories = this.initCategories(this.groupedSettings); - this.categoryCounts = this.initCategoryCounts(this.groupedSettings); - this.state = this.getQueryState(undefined, true); - this.unregister = this.props.history.listen(({ search }) => { - this.setState(this.getQueryState(search)); - }); - } - - init(config: IUiSettingsClient) { - this.settings = this.initSettings(config); - this.groupedSettings = this.initGroupedSettings(this.settings); - this.categories = this.initCategories(this.groupedSettings); - this.categoryCounts = this.initCategoryCounts(this.groupedSettings); - } - - initSettings = this.mapConfig; - initGroupedSettings = this.mapSettings; - initCategories(groupedSettings: GroupedSettings) { - return Object.keys(groupedSettings).sort((a, b) => { - if (a === DEFAULT_CATEGORY) return -1; - if (b === DEFAULT_CATEGORY) return 1; - if (a > b) return 1; - return a === b ? 0 : -1; - }); - } - initCategoryCounts(groupedSettings: GroupedSettings) { - return Object.keys(groupedSettings).reduce( - (counts: Record, category: string) => { - counts[category] = groupedSettings[category].length; - return counts; - }, - {} - ); } - componentDidMount() { - this.uiSettingsSubscription = this.props.uiSettings.getUpdate$().subscribe(() => { - const { query } = this.state; - this.init(this.props.uiSettings); - this.setState({ - filteredSettings: this.mapSettings(Query.execute(query, this.settings)), - }); - }); - - // scrolls to setting provided in the URL hash - const { hash } = window.location; - if (hash !== '') { - setTimeout(() => { - const id = hash.replace('#', ''); - const element = document.getElementById(id); - - let globalNavOffset = 0; - - const globalNavBars = document - .getElementById('globalHeaderBars') - ?.getElementsByClassName('euiHeader'); - - if (globalNavBars) { - Array.from(globalNavBars).forEach((navBar) => { - globalNavOffset += (navBar as HTMLDivElement).offsetHeight; - }); - } - - if (element) { - element.scrollIntoView(); - window.scrollBy(0, -globalNavOffset); // offsets scroll by height of the global nav - } - }, 0); - } - } - - componentWillUnmount() { - this.uiSettingsSubscription?.unsubscribe?.(); - this.unregister?.(); - } - - private getQuery(queryString: string, intialQuery = false): Query { - try { - const query = intialQuery ? getAriaName(queryString) : queryString ?? ''; - return Query.parse(query); - } catch ({ message }) { - this.props.toasts.addWarning({ - title: parseErrorMsg, - text: message, - }); - return Query.parse(''); - } - } - - private getQueryText(search?: string): string { - const queryParams = parse(search ?? window.location.search) ?? {}; - return (queryParams[QUERY] as string) ?? ''; - } - - private getQueryState(search?: string, intialQuery = false): AdvancedSettingsState { - const queryString = this.getQueryText(search); - const query = this.getQuery(queryString, intialQuery); - const filteredSettings = this.mapSettings(Query.execute(query, this.settings)); - const footerQueryMatched = Object.keys(filteredSettings).length > 0; - - return { - query, - filteredSettings, - footerQueryMatched, - }; - } - - setUrlQuery(q: string = '') { - const search = url.addQueryParam(window.location.search, QUERY, q); - - this.props.history.push({ - pathname: '', // remove any route query param - search, - }); - } - - mapConfig(config: IUiSettingsClient) { - const all = config.getAll(); - return Object.entries(all) - .map(([settingId, settingDef]) => { - return toEditableConfig({ - def: settingDef, - name: settingId, - value: settingDef.userValue, - isCustom: config.isCustom(settingId), - isOverridden: config.isOverridden(settingId), - }); - }) - .filter((c) => !c.readOnly) - .filter((c) => !c.isCustom) // hide any settings that aren't explicitly registered by enabled plugins. - .sort(fieldSorter); - } - - mapSettings(settings: FieldSetting[]) { - // Group settings by category - return settings.reduce((groupedSettings: GroupedSettings, setting) => { - // We will want to change this logic when we put each category on its - // own page aka allowing a setting to be included in multiple categories. - const category = setting.category[0]; - (groupedSettings[category] = groupedSettings[category] || []).push(setting); - return groupedSettings; - }, {}); - } - - onQueryChange = ({ query }: { query: Query }) => { - this.setUrlQuery(query.text); - }; - - clearQuery = () => { - this.setUrlQuery(''); - }; - - onFooterQueryMatchChange = (matched: boolean) => { - this.setState({ - footerQueryMatched: matched, - }); - }; - saveConfig = async (changes: SettingsChanges) => { const arr = Object.entries(changes).map(([key, value]) => - this.props.uiSettings.set(key, value) + this.props.uiSettingsClient.set(key, value) ); return Promise.all(arr); }; render() { - const { filteredSettings, query, footerQueryMatched } = this.state; - const componentRegistry = this.props.componentRegistry; - - const PageTitle = componentRegistry.get(componentRegistry.componentType.PAGE_TITLE_COMPONENT); - const PageSubtitle = componentRegistry.get( - componentRegistry.componentType.PAGE_SUBTITLE_COMPONENT - ); - const PageFooter = componentRegistry.get(componentRegistry.componentType.PAGE_FOOTER_COMPONENT); - return (
- - - - - - - - - - - - - - - - + + +

{this.props.callOutSubtitle}

+
+ + + +
-
); } diff --git a/src/plugins/advanced_settings/public/management_app/i18n_texts.ts b/src/plugins/advanced_settings/public/management_app/i18n_texts.ts new file mode 100644 index 0000000000000..d1edd5eed09e0 --- /dev/null +++ b/src/plugins/advanced_settings/public/management_app/i18n_texts.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { i18n } from '@kbn/i18n'; + +export const i18nTexts = { + defaultSpaceTabTitle: i18n.translate('advancedSettings.spaceSettingsTabTitle', { + defaultMessage: 'Space Settings', + }), + defaultSpaceCalloutTitle: i18n.translate('advancedSettings.defaultSpaceCalloutTitle', { + defaultMessage: 'Changes will affect the `default` space', + }), + defaultSpaceCalloutSubtitle: i18n.translate('advancedSettings.defaultSpaceCalloutSubtitle', { + defaultMessage: + 'Changes will only be applied to the current space. These settings are intended for advanced users, as improper configurations may adversely affect aspects of Kibana.', + }), + globalTabTitle: i18n.translate('advancedSettings.globalSettingsTabTitle', { + defaultMessage: 'Global Settings', + }), + globalCalloutTitle: i18n.translate('advancedSettings.globalCalloutTitle', { + defaultMessage: 'Changes will affect all user settings across all spaces', + }), + globalCalloutSubtitle: i18n.translate('advancedSettings.globalCalloutSubtitle', { + defaultMessage: + 'Changes will be applied to all users across all spaces. This includes both native Kibana users and single-sign on users.', + }), + advancedSettingsTitle: i18n.translate('advancedSettings.advancedSettingsLabel', { + defaultMessage: 'Advanced Settings', + }), +}; diff --git a/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx b/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx index e208ed80a3fdc..bbe7c36ee8206 100644 --- a/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx +++ b/src/plugins/advanced_settings/public/management_app/mount_management_section.tsx @@ -20,7 +20,8 @@ import { ManagementAppMountParams } from '@kbn/management-plugin/public'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; import { StartServicesAccessor } from '@kbn/core/public'; -import { AdvancedSettings, QUERY } from './advanced_settings'; +import { QUERY } from './advanced_settings'; +import { Settings } from './settings'; import { ComponentRegistry } from '../types'; import './index.scss'; @@ -59,7 +60,7 @@ export async function mountManagementSection( usageCollection?: UsageCollectionSetup ) { params.setBreadcrumbs(crumb); - const [{ uiSettings, notifications, docLinks, application, chrome }] = await getStartServices(); + const [{ settings, notifications, docLinks, application, chrome }] = await getStartServices(); const canSave = application.capabilities.advancedSettings.save as boolean; const trackUiMetric = usageCollection?.reportUiCounter.bind(usageCollection, 'advanced_settings'); @@ -78,12 +79,12 @@ export async function mountManagementSection( {/* TODO: remove route param (`query`) in 7.13 */} {(props) => } - { +describe('Settings', () => { const defaultQuery = 'test:string:setting'; const mockHistory = { listen: jest.fn(), @@ -244,12 +249,12 @@ describe('AdvancedSettings', () => { it('should render specific setting if given setting key', async () => { mockQuery(); const component = mountWithI18nProvider( - @@ -266,23 +271,24 @@ describe('AdvancedSettings', () => { it('should should not render a custom setting', async () => { // The manual mock for the uiSettings client returns false for isConfig, override that - const uiSettings = mockConfig().core.uiSettings; + const uiSettings = mockConfig().core.settings.client; uiSettings.isCustom = (key) => true; const customSettingQuery = 'test:customstring:setting'; mockQuery(customSettingQuery); const component = mountWithI18nProvider( - ); + expect(component.find('Field')).not.toBeNull(); expect( component .find('Field') @@ -296,17 +302,18 @@ describe('AdvancedSettings', () => { it('should render read-only when saving is disabled', async () => { mockQuery(); const component = mountWithI18nProvider( - ); + expect(component.find('Field')).not.toBeNull(); expect( component .find('Field') @@ -321,22 +328,20 @@ describe('AdvancedSettings', () => { const badQuery = 'category:(accessibility))'; mockQuery(badQuery); const { toasts } = notificationServiceMock.createStartContract(); - const getComponent = () => - shallowWithI18nProvider( - - ); - expect(getComponent).not.toThrow(); + const component = mountWithI18nProvider( + + ); + expect(toasts.addWarning).toHaveBeenCalledTimes(1); - const component = getComponent(); expect(component.find(Search).prop('query').text).toEqual(''); }); }); diff --git a/src/plugins/advanced_settings/public/management_app/settings.tsx b/src/plugins/advanced_settings/public/management_app/settings.tsx new file mode 100644 index 0000000000000..e3f9ad5991ed9 --- /dev/null +++ b/src/plugins/advanced_settings/public/management_app/settings.tsx @@ -0,0 +1,346 @@ +/* + * Copyright 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, { useState, useCallback, useMemo } from 'react'; +import useEffectOnce from 'react-use/lib/useEffectOnce'; +import { + EuiSpacer, + Query, + EuiNotificationBadge, + EuiTab, + EuiTabs, + EuiFlexGroup, + EuiFlexItem, + EuiText, +} from '@elastic/eui'; +import { ScopedHistory } from '@kbn/core-application-browser'; +import { SettingsStart } from '@kbn/core-ui-settings-browser'; +import { DocLinksStart } from '@kbn/core-doc-links-browser'; +import { ToastsStart } from '@kbn/core-notifications-browser'; +import { ThemeServiceStart } from '@kbn/core-theme-browser'; +import { UiCounterMetricType } from '@kbn/analytics'; +import { url } from '@kbn/kibana-utils-plugin/common'; +import { parse } from 'query-string'; +import { UiSettingsScope } from '@kbn/core-ui-settings-common'; +import { mapConfig, mapSettings, initCategoryCounts, initCategories } from './settings_helper'; +import { parseErrorMsg } from './components/search/search'; +import { AdvancedSettings, QUERY } from './advanced_settings'; +import { ComponentRegistry } from '..'; +import { Search } from './components/search'; +import { FieldSetting } from './types'; +import { i18nTexts } from './i18n_texts'; +import { getAriaName } from './lib'; + +interface AdvancedSettingsState { + footerQueryMatched: boolean; + query: Query; + filteredSettings: Record>; +} + +export type GroupedSettings = Record; + +interface Props { + history: ScopedHistory; + enableSaving: boolean; + settingsService: SettingsStart; + docLinks: DocLinksStart['links']; + toasts: ToastsStart; + theme: ThemeServiceStart['theme$']; + componentRegistry: ComponentRegistry['start']; + trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; +} + +const SPACE_SETTINGS_ID = 'space-settings'; +const GLOBAL_SETTINGS_ID = 'global-settings'; + +export const Settings = (props: Props) => { + const { componentRegistry, history, settingsService, ...rest } = props; + const uiSettings = settingsService.client; + const globalUiSettings = settingsService.globalClient; + + const [settings, setSettings] = useState(mapConfig(uiSettings)); + const [globalSettings, setGlobalSettings] = useState(mapConfig(globalUiSettings)); + + const [groupedSettings, setGroupedSettings] = useState>({ + namespace: mapSettings(settings), + global: mapSettings(globalSettings), + }); + + const [categoryCounts, setCategoryCounts] = useState< + Record> + >({ + namespace: initCategoryCounts(groupedSettings.namespace), + global: initCategoryCounts(groupedSettings.global), + }); + + const [categories, setCategories] = useState>({ + namespace: initCategories(groupedSettings.namespace), + global: initCategories(groupedSettings.global), + }); + + const [queryState, setQueryState] = useState({ + filteredSettings: { + global: {}, + namespace: {}, + }, + footerQueryMatched: false, + query: Query.parse(''), + }); + + const setTimeoutCallback = () => { + const { hash } = window.location; + const id = hash.replace('#', ''); + const element = document.getElementById(id); + + let globalNavOffset = 0; + + const globalNavBars = document + .getElementById('globalHeaderBars') + ?.getElementsByClassName('euiHeader'); + + if (globalNavBars) { + Array.from(globalNavBars).forEach((navBar) => { + globalNavOffset += (navBar as HTMLDivElement).offsetHeight; + }); + } + + if (element) { + element.scrollIntoView(); + window.scrollBy(0, -globalNavOffset); // offsets scroll by height of the global nav + } + }; + + useEffectOnce(() => { + setQueryState(getQueryState(undefined, true)); + + const subscription = (mappedSettings: FieldSetting[], scope: UiSettingsScope) => { + const grouped = { ...groupedSettings }; + grouped[scope] = mapSettings(mappedSettings); + setGroupedSettings(grouped); + + const updatedCategories = { ...categories }; + updatedCategories[scope] = initCategories(groupedSettings[scope]); + setCategories(updatedCategories); + + const updatedCategoryCounts = { ...categoryCounts }; + updatedCategoryCounts[scope] = initCategoryCounts(groupedSettings[scope]); + setCategoryCounts(updatedCategoryCounts); + const updatedQueryState = { ...getQueryState(undefined, true) }; + updatedQueryState.filteredSettings[scope] = mapSettings( + Query.execute(updatedQueryState.query, mappedSettings) + ); + setQueryState(updatedQueryState); + }; + + const uiSettingsSubscription = uiSettings.getUpdate$().subscribe(() => { + const updatedSettings = mapConfig(uiSettings); + setSettings(updatedSettings); + subscription(updatedSettings, 'namespace'); + }); + const globalUiSettingsSubscription = globalUiSettings.getUpdate$().subscribe(() => { + const mappedSettings = mapConfig(globalUiSettings); + setGlobalSettings(mappedSettings); + subscription(mappedSettings, 'global'); + }); + if (window.location.hash !== '') { + setTimeout(() => setTimeoutCallback(), 0); + } + const unregister = history.listen(({ search }) => { + setQueryState(getQueryState(search)); + }); + return () => { + unregister(); + uiSettingsSubscription.unsubscribe(); + globalUiSettingsSubscription.unsubscribe(); + }; + }); + + const setUrlQuery = useCallback( + (query: string = '') => { + const search = url.addQueryParam(window.location.search, QUERY, query); + + history.push({ + pathname: '', // remove any route query param + search, + }); + }, + [history] + ); + + const searchCategories = useMemo(() => { + return categories.global.concat(categories.namespace); + }, [categories.global, categories.namespace]); + + const callOutTitle = (scope: UiSettingsScope) => { + if (scope === 'namespace') { + return i18nTexts.defaultSpaceCalloutTitle; + } + return i18nTexts.globalCalloutTitle; + }; + + const callOutSubtitle = (scope: UiSettingsScope) => { + if (scope === 'namespace') { + return i18nTexts.defaultSpaceCalloutSubtitle; + } + return i18nTexts.globalCalloutSubtitle; + }; + + const getClientForScope = (scope: UiSettingsScope) => { + if (scope === 'namespace') { + return uiSettings; + } + return globalUiSettings; + }; + + const renderAdvancedSettings = (scope: UiSettingsScope) => { + return ( + setUrlQuery('')} + noResults={!queryState.footerQueryMatched} + queryText={queryState.query.text} + callOutTitle={callOutTitle(scope)} + callOutSubtitle={callOutSubtitle(scope)} + settingsService={settingsService} + uiSettingsClient={getClientForScope(scope)} + {...rest} + /> + ); + }; + + const tabs = [ + { + id: SPACE_SETTINGS_ID, + name: i18nTexts.defaultSpaceTabTitle, + append: + queryState.query.text !== '' ? ( + + {Object.keys(queryState.filteredSettings.namespace).length} + + ) : null, + content: renderAdvancedSettings('namespace'), + }, + { + id: GLOBAL_SETTINGS_ID, + name: i18nTexts.globalTabTitle, + append: + queryState.query.text !== '' ? ( + + {Object.keys(queryState.filteredSettings.global).length + + Number(queryState.footerQueryMatched)} + + ) : null, + content: renderAdvancedSettings('global'), + }, + ]; + + const [selectedTabId, setSelectedTabId] = useState(SPACE_SETTINGS_ID); + + const selectedTabContent = tabs.find((obj) => obj.id === selectedTabId)?.content; + + const onSelectedTabChanged = (id: string) => { + setSelectedTabId(id); + }; + + const renderTabs = () => { + return tabs.map((tab, index) => ( + onSelectedTabChanged(tab.id)} + isSelected={tab.id === selectedTabId} + append={tab.append} + > + {tab.name} + + )); + }; + + const getQuery = (queryString: string, initialQuery = false): Query => { + try { + const query = initialQuery ? getAriaName(queryString) : queryString ?? ''; + return Query.parse(query); + } catch ({ message }) { + props.toasts.addWarning({ + title: parseErrorMsg, + text: message, + }); + return Query.parse(''); + } + }; + + const getQueryText = (search?: string): string => { + const queryParams = parse(search ?? window.location.search) ?? {}; + return (queryParams[QUERY] as string) ?? ''; + }; + + const getQueryState = (search?: string, intialQuery = false): AdvancedSettingsState => { + const queryString = getQueryText(search); + const query = getQuery(queryString, intialQuery); + const filteredSettings = { + namespace: mapSettings(Query.execute(query, settings)), + global: mapSettings(Query.execute(query, globalSettings)), + }; + const footerQueryMatched = Object.keys(filteredSettings.namespace).length > 0; + + return { + query, + filteredSettings, + footerQueryMatched, + }; + }; + + const onQueryChange = useCallback( + ({ query }: { query: Query }) => { + setUrlQuery(query.text); + }, + [setUrlQuery] + ); + + const onFooterQueryMatchChange = useCallback( + (matched: boolean) => { + setQueryState({ ...queryState, footerQueryMatched: matched }); + }, + [queryState] + ); + + const PageTitle = ( + +

{i18nTexts.advancedSettingsTitle}

+
+ ); + const PageFooter = componentRegistry.get(componentRegistry.componentType.PAGE_FOOTER_COMPONENT); + + return ( +
+ + {PageTitle} + + + + + + {renderTabs()} + {selectedTabContent} + {selectedTabId === GLOBAL_SETTINGS_ID ? ( + + ) : null} +
+ ); +}; diff --git a/src/plugins/advanced_settings/public/management_app/settings_helper.test.ts b/src/plugins/advanced_settings/public/management_app/settings_helper.test.ts new file mode 100644 index 0000000000000..7f745db9b786b --- /dev/null +++ b/src/plugins/advanced_settings/public/management_app/settings_helper.test.ts @@ -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 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 { UiSettingsType, UserProvidedValues } from '@kbn/core-ui-settings-common'; +import { PublicUiSettingsParams } from '@kbn/core/public'; +import { Observable } from 'rxjs'; +import { FieldSetting } from './types'; +import { mapConfig, mapSettings, initCategoryCounts, initCategories } from './settings_helper'; + +describe('Settings Helper', () => { + const defaultConfig: Partial = { + displayName: 'defaultName', + requiresPageReload: false, + isOverridden: false, + ariaName: 'ariaName', + readOnly: false, + isCustom: false, + defVal: 'defVal', + type: 'string' as UiSettingsType, + category: ['category'], + }; + + const arraySetting = { + 'test:array:setting': { + ...defaultConfig, + value: ['default_value'], + name: 'Test array setting', + description: 'Description for Test array setting', + category: ['elasticsearch'], + }, + }; + + const booleanSetting = { + 'test:boolean:setting': { + ...defaultConfig, + value: true, + name: 'Test boolean setting', + description: 'Description for Test boolean setting', + category: ['elasticsearch'], + }, + }; + + const imageSetting = { + 'test:image:setting': { + ...defaultConfig, + value: null, + name: 'Test image setting', + description: 'Description for Test image setting', + type: 'image' as UiSettingsType, + }, + }; + + const arrayFieldSetting = { + ariaName: 'Test array setting', + category: ['elasticsearch'], + defVal: ['default_value'], + description: 'Description for Test array setting', + displayName: 'Test array setting', + isCustom: false, + isOverridden: false, + name: 'test:array:setting', + readOnly: false, + requiresPageReload: false, + type: 'string' as UiSettingsType, + }; + + const booleanFieldSetting = { + ariaName: 'Test boolean setting', + category: ['elasticsearch'], + defVal: true, + description: 'Description for Test boolean setting', + displayName: 'Test boolean setting', + isCustom: false, + isOverridden: false, + name: 'test:boolean:setting', + readOnly: false, + requiresPageReload: false, + type: 'string' as UiSettingsType, + }; + + const imageFieldSetting = { + ariaName: 'Test image setting', + category: ['category'], + defVal: null, + description: 'Description for Test image setting', + displayName: 'Test image setting', + isCustom: false, + isOverridden: false, + name: 'test:image:setting', + readOnly: false, + requiresPageReload: false, + type: 'image' as UiSettingsType, + }; + + const config = { + set: (key: string, value: any) => Promise.resolve(true), + remove: (key: string) => Promise.resolve(true), + isCustom: (key: string) => false, + isOverridden: (key: string) => Boolean(config.getAll()[key].isOverridden), + getRegistered: () => ({} as Readonly>), + getUpdate$: () => + new Observable<{ + key: string; + newValue: any; + oldValue: any; + }>(), + isDeclared: (key: string) => true, + isDefault: (key: string) => true, + + getSaved$: () => + new Observable<{ + key: string; + newValue: any; + oldValue: any; + }>(), + + getUpdateErrors$: () => new Observable(), + get: (key: string, defaultOverride?: any): any => config.getAll()[key] || defaultOverride, + get$: (key: string) => new Observable(config.get(key)), + getAll: (): Readonly> => { + return { + ...arraySetting, + ...booleanSetting, + ...imageSetting, + }; + }, + }; + + it('mapConfig', () => { + expect(mapConfig(config)).toEqual([arrayFieldSetting, booleanFieldSetting, imageFieldSetting]); + }); + + it('mapSettings, initCategoryCounts and initCategories', () => { + const fieldSetting1: FieldSetting = { ...arrayFieldSetting, value: ['a', 'b', 'c'] }; + const fieldSetting2: FieldSetting = { ...booleanFieldSetting, value: false }; + const fieldSetting3: FieldSetting = { ...imageFieldSetting, value: 'imageSrc' }; + const mapped = mapSettings([fieldSetting1, fieldSetting2, fieldSetting3]); + expect(Object.keys(mapped).sort()).toEqual(['category', 'elasticsearch'].sort()); + expect(mapped.category.length).toEqual(1); + expect(mapped.elasticsearch.length).toEqual(2); + + const categoryCounts = initCategoryCounts(mapped); + expect(categoryCounts).toEqual({ category: 1, elasticsearch: 2 }); + + const categories = initCategories(mapped); + expect(categories).toEqual(['category', 'elasticsearch']); + }); +}); diff --git a/src/plugins/advanced_settings/public/management_app/settings_helper.ts b/src/plugins/advanced_settings/public/management_app/settings_helper.ts new file mode 100644 index 0000000000000..15921f2dd77c4 --- /dev/null +++ b/src/plugins/advanced_settings/public/management_app/settings_helper.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { DEFAULT_CATEGORY, fieldSorter, toEditableConfig } from './lib'; +import { FieldSetting } from './types'; +import { GroupedSettings } from './settings'; + +export const mapConfig = (config: IUiSettingsClient) => { + const all = config.getAll(); + return Object.entries(all) + .map(([settingId, settingDef]) => { + return toEditableConfig({ + def: settingDef, + name: settingId, + value: settingDef.userValue, + isCustom: config.isCustom(settingId), + isOverridden: config.isOverridden(settingId), + }); + }) + .filter((c) => !c.readOnly) + .filter((c) => !c.isCustom) // hide any settings that aren't explicitly registered by enabled plugins. + .sort(fieldSorter); +}; + +export const mapSettings = (fieldSettings: FieldSetting[]) => { + // Group settings by category + return fieldSettings.reduce((grouped: GroupedSettings, setting) => { + // We will want to change this logic when we put each category on its + // own page aka allowing a setting to be included in multiple categories. + const category = setting.category[0]; + (grouped[category] = grouped[category] || []).push(setting); + return grouped; + }, {}); +}; + +export const initCategoryCounts = (grouped: GroupedSettings) => { + return Object.keys(grouped).reduce((counts: Record, category: string) => { + counts[category] = grouped[category].length; + return counts; + }, {}); +}; + +export const initCategories = (grouped: GroupedSettings) => { + return Object.keys(grouped).sort((a, b) => { + if (a === DEFAULT_CATEGORY) return -1; + if (b === DEFAULT_CATEGORY) return 1; + if (a > b) return 1; + return a === b ? 0 : -1; + }); +}; diff --git a/src/plugins/advanced_settings/tsconfig.json b/src/plugins/advanced_settings/tsconfig.json index 17a6f098a6185..e5a2db29d0fdb 100644 --- a/src/plugins/advanced_settings/tsconfig.json +++ b/src/plugins/advanced_settings/tsconfig.json @@ -20,6 +20,13 @@ "@kbn/i18n-react", "@kbn/expect", "@kbn/monaco", + "@kbn/core-ui-settings-browser-mocks", + "@kbn/core-application-browser", + "@kbn/core-ui-settings-browser", + "@kbn/core-doc-links-browser", + "@kbn/core-notifications-browser", + "@kbn/core-theme-browser", + "@kbn/core-ui-settings-common", ], "exclude": [ "target/**/*", diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index ddc80ea5dd774..816f3a7635a12 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -37,7 +37,12 @@ export { overviewPageActions, OverviewPageFooter } from './overview_page'; export type { KibanaReactOverlays } from './overlays'; export { createReactOverlays } from './overlays'; -export { useUiSetting, useUiSetting$ } from './ui_settings'; +export { + useUiSetting, + useGlobalUiSetting, + useUiSetting$, + useGlobalUiSetting$, +} from './ui_settings'; export { useExecutionContext } from './use_execution_context'; diff --git a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx index 466af1ad18324..cca2ded991db2 100644 --- a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx +++ b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.test.tsx @@ -9,7 +9,7 @@ import * as React from 'react'; import * as ReactDOM from 'react-dom'; import { act, Simulate } from 'react-dom/test-utils'; -import { useUiSetting$ } from './use_ui_setting'; +import { useGlobalUiSetting$, useUiSetting$ } from './use_ui_setting'; import { createKibanaReactContext } from '../context'; import { KibanaServices } from '../context/types'; import { Subject } from 'rxjs'; @@ -94,6 +94,67 @@ describe('useUiSetting', () => { }); }); +describe('useGlobalUiSetting', () => { + const mockGlobal = (): [KibanaServices, Subject] => { + const core = coreMock.createStart(); + const get = core.settings.globalClient.get; + const get$ = core.settings.globalClient.get$; + const subject = new Subject(); + + get.mockImplementation(() => 'baz'); + get$.mockImplementation(() => subject); + + return [core, subject]; + }; + + const TestConsumer: React.FC<{ + setting: string; + newValue?: string; + }> = ({ setting, newValue = '' }) => { + const [value, set] = useGlobalUiSetting$(setting, 'default'); + + return ( +
+ {setting}: {value} + +
+ ); + }; + + test('returns setting value', async () => { + const [core] = mockGlobal(); + const { Provider } = createKibanaReactContext(core); + + ReactDOM.render( + + + , + container + ); + + const strong = container!.querySelector('strong'); + expect(strong!.textContent).toBe('baz'); + expect(core.settings!.globalClient.get).toHaveBeenCalledTimes(1); + expect((core.settings!.globalClient.get as any).mock.calls[0][0]).toBe('foo'); + }); + + test('calls uiSettings.get() method with correct key and default value', async () => { + const [core] = mockGlobal(); + const { Provider } = createKibanaReactContext(core); + + ReactDOM.render( + + + , + container + ); + + expect(core.settings!.globalClient.get).toHaveBeenCalledTimes(1); + expect((core.settings!.globalClient.get as any).mock.calls[0][0]).toBe('fooBar'); + expect((core.settings!.globalClient.get as any).mock.calls[0][1]).toBe('default'); + }); +}); + describe('useUiSetting$', () => { const TestConsumerX: React.FC<{ setting: string; diff --git a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts index d73b8721c7f47..d75e4cb96cfa3 100644 --- a/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts +++ b/src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts @@ -29,6 +29,25 @@ export const useUiSetting = (key: string, defaultValue?: T): T => { return services.uiSettings.get(key, defaultValue); }; +/** + * Returns the current global UI-settings value. + * + * Usage: + * + * ```js + * const customBranding = useGlobalUiSetting('customBranding:pageTitle'); + * ``` + */ +export const useGlobalUiSetting = (key: string, defaultValue?: T): T => { + const { services } = useKibana(); + + if (typeof services.settings !== 'object') { + throw new TypeError('uiSettings service not available in kibana-react context.'); + } + + return services.settings.globalClient.get(key, defaultValue); +}; + type Setter = (newValue: T) => Promise; /** @@ -60,3 +79,39 @@ export const useUiSetting$ = (key: string, defaultValue?: T): [T, Setter] return [value, set]; }; + +/** + * Returns a 2-tuple, where first entry is the setting value and second is a + * function to update the setting value. + * + * Synchronously returns the most current value of the setting and subscribes + * to all subsequent updates, which will re-render your component on new values. + * + * Usage: + * + * ```js + * const [customBranding, setCustomBranding] = useGlobalUiSetting$('customBranding:pageTitle'); + * ``` + */ +export const useGlobalUiSetting$ = (key: string, defaultValue?: T): [T, Setter] => { + const { services } = useKibana(); + + if (typeof services.settings !== 'object') { + throw new TypeError('uiSettings service not available in kibana-react context.'); + } + + const observable$ = useMemo( + () => services.settings!.globalClient.get$(key, defaultValue), + [key, defaultValue, services.settings!.globalClient] + ); + const value = useObservable( + observable$, + services.settings!.globalClient.get(key, defaultValue) + ); + const set = useCallback( + (newValue: T) => services.settings!.globalClient.set(key, newValue), + [key] + ); + + return [value, set]; +}; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index df4eefe6efa18..d46c9c86ef94e 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -125,7 +125,6 @@ "advancedSettings.form.saveButtonLabel": "Enregistrer les modifications", "advancedSettings.form.saveButtonTooltipWithInvalidChanges": "Corrigez les paramètres non valides avant d'enregistrer.", "advancedSettings.form.saveErrorMessage": "Enregistrement impossible", - "advancedSettings.pageTitle": "Paramètres", "advancedSettings.searchBar.unableToParseQueryErrorMessage": "Impossible d'analyser la requête", "advancedSettings.searchBarAriaLabel": "Rechercher dans les paramètres avancés", "advancedSettings.voiceAnnouncement.ariaLabel": "Informations de résultat des paramètres avancés", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7cb33c2275dcc..ccd32864c7028 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -125,7 +125,6 @@ "advancedSettings.form.saveButtonLabel": "変更を保存", "advancedSettings.form.saveButtonTooltipWithInvalidChanges": "保存前に無効な設定を修正してください。", "advancedSettings.form.saveErrorMessage": "を保存できませんでした", - "advancedSettings.pageTitle": "設定", "advancedSettings.searchBar.unableToParseQueryErrorMessage": "クエリをパースできません", "advancedSettings.searchBarAriaLabel": "高度な設定を検索", "advancedSettings.voiceAnnouncement.ariaLabel": "詳細設定結果情報", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index dde2c552434b2..57f2ed771fad5 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -125,7 +125,6 @@ "advancedSettings.form.saveButtonLabel": "保存更改", "advancedSettings.form.saveButtonTooltipWithInvalidChanges": "保存前请修复无效的设置。", "advancedSettings.form.saveErrorMessage": "无法保存", - "advancedSettings.pageTitle": "设置", "advancedSettings.searchBar.unableToParseQueryErrorMessage": "无法解析查询", "advancedSettings.searchBarAriaLabel": "搜索高级设置", "advancedSettings.voiceAnnouncement.ariaLabel": "“高级设置”的结果信息", From 515eeabf397bb0f61a49b80a1ef06f9cfea2a5b2 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 9 Feb 2023 08:39:32 +0100 Subject: [PATCH 002/203] [Synthetics] Display half completed journey errors (#150530) Co-authored-by: Abdul Zahid Fixes https://github.com/elastic/kibana/issues/150128 --- .../common/components/stderr_logs.tsx | 5 ++ .../browser_steps_list.tsx | 24 +++++-- .../browser/browser_test_results.tsx | 70 +++++++++++++++---- .../components/step_details.tsx | 2 +- .../components/test_run_details/step_tabs.tsx | 10 +-- .../test_run_details/test_run_details.tsx | 2 +- 6 files changed, 90 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/stderr_logs.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/stderr_logs.tsx index 2c105cec59d3e..e58a105e80238 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/stderr_logs.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/stderr_logs.tsx @@ -36,6 +36,7 @@ export const StdErrorLogs = ({ title, summaryMessage, hideTitle = false, + pageSize = 5, }: { monitorId?: string; checkGroup?: string; @@ -43,6 +44,7 @@ export const StdErrorLogs = ({ title?: string; summaryMessage?: string; hideTitle?: boolean; + pageSize?: number; }) => { const columns = [ { @@ -129,6 +131,9 @@ export const StdErrorLogs = ({ executeQueryOptions={{ defaultFields: ['@timestamp', 'synthetics.payload.message'], }} + pagination={{ + pageSize, + }} /> ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx index 64ed7b366c245..a343a67021f0b 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/browser_steps_list.tsx @@ -11,11 +11,14 @@ import { EuiBasicTable, EuiBasicTableColumn, EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, EuiText, useEuiTheme, } from '@elastic/eui'; import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; +import { StepTabs } from '../../test_run_details/step_tabs'; import { ResultDetails } from './result_details'; import { JourneyStep } from '../../../../../../common/runtime_types'; import { JourneyStepScreenshotContainer } from '../screenshot/journey_step_screenshot_container'; @@ -34,6 +37,8 @@ interface Props { screenshotImageSize?: ScreenshotImageSize; compressed?: boolean; showExpand?: boolean; + testNowMode?: boolean; + showLastSuccessful?: boolean; } export function isStepEnd(step: JourneyStep) { @@ -45,9 +50,11 @@ export const BrowserStepsList = ({ error, loading, screenshotImageSize = THUMBNAIL_SCREENSHOT_SIZE, + showLastSuccessful = true, showStepNumber = false, compressed = true, showExpand = true, + testNowMode = false, }: Props) => { const { euiTheme } = useEuiTheme(); const stepEnds: JourneyStep[] = steps.filter(isStepEnd); @@ -60,13 +67,21 @@ export const BrowserStepsList = ({ if (itemIdToExpandedRowMapValues[item._id]) { delete itemIdToExpandedRowMapValues[item._id]; } else { - itemIdToExpandedRowMapValues[item._id] = <>; + if (testNowMode) { + itemIdToExpandedRowMapValues[item._id] = ( + + + + + + ); + } else { + itemIdToExpandedRowMapValues[item._id] = <>; + } } setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); }; - const showLastSuccessful = true; - const columns: Array> = [ ...(showExpand ? [ @@ -145,7 +160,7 @@ export const BrowserStepsList = ({ ), }, @@ -218,6 +233,7 @@ export const BrowserStepsList = ({ } tableLayout={'auto'} itemId="_id" + itemIdToExpandedRowMap={testNowMode ? itemIdToExpandedRowMap : undefined} /> ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_now_mode/browser/browser_test_results.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_now_mode/browser/browser_test_results.tsx index ca8680ca4d823..d2c497007b55f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_now_mode/browser/browser_test_results.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_now_mode/browser/browser_test_results.tsx @@ -7,7 +7,16 @@ import { useEffect } from 'react'; import * as React from 'react'; -import { EuiAccordion, EuiText, EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui'; +import { + EuiAccordion, + EuiText, + EuiFlexGroup, + EuiFlexItem, + EuiLoadingSpinner, + EuiTitle, + EuiCallOut, + useEuiTheme, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import styled from 'styled-components'; import { BrowserStepsList } from '../../common/monitor_test_result/browser_steps_list'; @@ -24,6 +33,7 @@ interface Props { onDone: (testRunId: string) => void; } export const BrowserTestRunResult = ({ expectPings, onDone, testRunId }: Props) => { + const { euiTheme } = useEuiTheme(); const { summariesLoading, expectedSummariesLoaded, stepLoadingInProgress, checkGroupResults } = useBrowserRunOnceMonitors({ testRunId, @@ -45,6 +55,8 @@ export const BrowserTestRunResult = ({ expectPings, onDone, testRunId }: Props) const isStepsLoadingFailed = summaryDoc && !summariesLoading && !stepLoadingInProgress && steps.length === 0; + const isDownMonitor = summaryDoc?.monitor?.status === 'down'; + return ( )} - {isStepsLoadingFailed && ( - {summaryDoc?.error?.message ?? FAILED_TO_RUN} + + {(isStepsLoadingFailed || isDownMonitor) && ( + + {summaryDoc?.error?.message ?? FAILED_TO_RUN} + )} - {isStepsLoadingFailed && + {(isStepsLoadingFailed || isDownMonitor) && summaryDoc?.error?.message?.includes('journey did not finish executing') && ( - + )} {completedSteps > 0 && ( - + <> + +

{STEPS_LABEL}

+
+ + )}
); @@ -136,6 +174,14 @@ const FAILED_TO_RUN = i18n.translate('xpack.synthetics.monitorManagement.failedR defaultMessage: 'Failed to run steps', }); +const ERROR_RUNNING_TEST = i18n.translate('xpack.synthetics.testRun.runErrorLabel', { + defaultMessage: 'Error running test', +}); + const LOADING_STEPS = i18n.translate('xpack.synthetics.monitorManagement.loadingSteps', { defaultMessage: 'Loading steps...', }); + +const STEPS_LABEL = i18n.translate('xpack.synthetics.monitorManagement.steps', { + defaultMessage: 'Steps', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/components/step_details.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/components/step_details.tsx index 79a6c3d9081bc..78952c85c1584 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/components/step_details.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/components/step_details.tsx @@ -61,7 +61,7 @@ export const StepDetails = ({ - + ); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_tabs.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_tabs.tsx index cfc9c877added..294d065bd7b00 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_tabs.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/step_tabs.tsx @@ -13,11 +13,11 @@ import { JourneyStep, SyntheticsJourneyApiResponse } from '../../../../../common type TabId = 'code' | 'console' | 'stackTrace'; export const StepTabs = ({ - stepsData, + stepsList, step, loading, }: { - stepsData?: SyntheticsJourneyApiResponse; + stepsList?: SyntheticsJourneyApiResponse['steps']; step?: JourneyStep; loading: boolean; }) => { @@ -105,15 +105,15 @@ export const StepTabs = ({ const getBrowserConsoles = useCallback( (index: number) => { - return stepsData?.steps - .filter( + return stepsList + ?.filter( (stepF) => stepF.synthetics?.type === 'journey/browserconsole' && stepF.synthetics?.step?.index! === index ) .map((stepF) => stepF.synthetics?.payload?.text!); }, - [stepsData?.steps] + [stepsList] ); return ( diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx index a0cff11450bdf..a72ccdeb3fa65 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/test_run_details/test_run_details.tsx @@ -76,7 +76,7 @@ export const TestRunDetails = () => { - + From 959e238b23fd630be1f738dbae1f2884f1f999cd Mon Sep 17 00:00:00 2001 From: Bena Kansara <69037875+benakansara@users.noreply.github.com> Date: Thu, 9 Feb 2023 10:23:36 +0100 Subject: [PATCH 003/203] Change description of context.group action variable (#150104) ## Summary This PR changes the description of `context.group` action variable in Metric threshold rule and Log threshold rule. The background of this change can be found in [this PR](https://github.com/elastic/kibana/pull/149071#issuecomment-1409135804). ## Metric threshold rule **Old description:** Name of the group reporting data **New description:** Name of the group(s) reporting data. For accessing each group key, use context.groupByKeys. Screenshot 2023-02-01 at 21 30 34 ## Log threshold rule **Old description:** The name of the group responsible for triggering the alert **New description:** The name of the group(s) responsible for triggering the alert. For accessing each group key, use context.groupByKeys. Screenshot 2023-02-01 at 21 26 41 @maciejforcone please let me know in case the wording should be changed. ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) --- .../plugins/infra/server/lib/alerting/common/messages.ts | 7 ------- .../register_inventory_metric_threshold_rule_type.ts | 8 +++++++- .../log_threshold/register_log_threshold_rule_type.ts | 3 ++- .../register_metric_threshold_rule_type.ts | 9 ++++++++- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts index ab7b0490aa901..9a7c9d2764486 100644 --- a/x-pack/plugins/infra/server/lib/alerting/common/messages.ts +++ b/x-pack/plugins/infra/server/lib/alerting/common/messages.ts @@ -162,13 +162,6 @@ export const buildInvalidQueryAlertReason = (filterQueryText: string) => }, }); -export const groupActionVariableDescription = i18n.translate( - 'xpack.infra.metrics.alerting.groupActionVariableDescription', - { - defaultMessage: 'Name of the group reporting data', - } -); - export const groupByKeysActionVariableDescription = i18n.translate( 'xpack.infra.metrics.alerting.groupByKeysActionVariableDescription', { diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts index b0b8a13562feb..998a0d7051f0a 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts @@ -28,7 +28,6 @@ import { alertStateActionVariableDescription, cloudActionVariableDescription, containerActionVariableDescription, - groupActionVariableDescription, hostActionVariableDescription, labelsActionVariableDescription, metricActionVariableDescription, @@ -75,6 +74,13 @@ const condition = schema.object({ ), }); +const groupActionVariableDescription = i18n.translate( + 'xpack.infra.inventory.alerting.groupActionVariableDescription', + { + defaultMessage: 'Name of the group reporting data', + } +); + export async function registerMetricInventoryThresholdRuleType( alertingPlugin: PluginSetupContract, libs: InfraBackendLibs diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts index 3cd1dcee6f4e8..09f46c98c1719 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/register_log_threshold_rule_type.ts @@ -51,7 +51,8 @@ const conditionsActionVariableDescription = i18n.translate( const groupByActionVariableDescription = i18n.translate( 'xpack.infra.logs.alerting.threshold.groupByActionVariableDescription', { - defaultMessage: 'The name of the group responsible for triggering the alert', + defaultMessage: + 'The name of the group(s) responsible for triggering the alert. For accessing each group key, use context.groupByKeys.', } ); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts index b9d069db244fb..2b7074ac2956e 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_rule_type.ts @@ -17,7 +17,6 @@ import { alertStateActionVariableDescription, cloudActionVariableDescription, containerActionVariableDescription, - groupActionVariableDescription, groupByKeysActionVariableDescription, hostActionVariableDescription, labelsActionVariableDescription, @@ -108,6 +107,14 @@ export async function registerMetricThresholdRuleType( label: schema.maybe(schema.string()), }); + const groupActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.groupActionVariableDescription', + { + defaultMessage: + 'Name of the group(s) reporting data. For accessing each group key, use context.groupByKeys.', + } + ); + alertingPlugin.registerType({ id: METRIC_THRESHOLD_ALERT_TYPE_ID, name: i18n.translate('xpack.infra.metrics.alertName', { From 7981e47262808e589cdf0fa82c3318020f0d41d4 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Thu, 9 Feb 2023 11:31:54 +0200 Subject: [PATCH 004/203] [Cases] Make spaces plugin optional (#150252) ## Summary This PR makes the spaces plugin an optional dependency for the cases plugin. Related: https://github.com/elastic/kibana/issues/149687 ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- x-pack/plugins/cases/kibana.jsonc | 4 +-- .../authorization/authorization.test.ts | 32 +++++++++++++++++++ .../server/authorization/authorization.ts | 10 +++--- x-pack/plugins/cases/server/client/factory.ts | 9 ++++-- x-pack/plugins/cases/server/plugin.ts | 2 +- .../server/services/user_profiles/index.ts | 5 +-- 6 files changed, 50 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/cases/kibana.jsonc b/x-pack/plugins/cases/kibana.jsonc index 0bda577c93623..1f474ccf8e9d4 100644 --- a/x-pack/plugins/cases/kibana.jsonc +++ b/x-pack/plugins/cases/kibana.jsonc @@ -23,14 +23,14 @@ "kibanaUtils", "triggersActionsUi", "management", - "spaces", "security", "notifications" ], "optionalPlugins": [ "home", "taskManager", - "usageCollection" + "usageCollection", + "spaces" ], "requiredBundles": [ "savedObjects" diff --git a/x-pack/plugins/cases/server/authorization/authorization.test.ts b/x-pack/plugins/cases/server/authorization/authorization.test.ts index 0945555689fbf..d02b8f011cf75 100644 --- a/x-pack/plugins/cases/server/authorization/authorization.test.ts +++ b/x-pack/plugins/cases/server/authorization/authorization.test.ts @@ -69,6 +69,38 @@ describe('authorization', () => { await expect(authPromise).resolves.not.toThrow(); }); + it('creates an Authorization object without spaces', async () => { + expect.assertions(2); + + const authPromise = Authorization.create({ + request, + securityAuth: securityStart.authz, + features: featuresStart, + auditLogger: new AuthorizationAuditLogger(mockLogger), + logger: loggingSystemMock.createLogger(), + }); + + await expect(authPromise).resolves.toBeDefined(); + await expect(authPromise).resolves.not.toThrow(); + }); + + it('if spaces are disabled it does not filtered out disabled features', async () => { + (spacesStart.spacesService.getActiveSpace as jest.Mock).mockImplementation(() => { + return { disabledFeatures: ['1'] } as Space; + }); + + const auth = await Authorization.create({ + request, + securityAuth: securityStart.authz, + features: featuresStart, + auditLogger: new AuthorizationAuditLogger(mockLogger), + logger: loggingSystemMock.createLogger(), + }); + + // @ts-expect-error: featureCaseOwners is a private method of the auth class + expect([...auth.featureCaseOwners.values()]).toEqual(['a']); + }); + it('throws and error when a failure occurs', async () => { expect.assertions(1); diff --git a/x-pack/plugins/cases/server/authorization/authorization.ts b/x-pack/plugins/cases/server/authorization/authorization.ts index 14ecaa6111f8c..e3dc970b38182 100644 --- a/x-pack/plugins/cases/server/authorization/authorization.ts +++ b/x-pack/plugins/cases/server/authorization/authorization.ts @@ -57,19 +57,21 @@ export class Authorization { }: { request: KibanaRequest; securityAuth?: SecurityPluginStart['authz']; - spaces: SpacesPluginStart; + spaces?: SpacesPluginStart; features: FeaturesPluginStart; auditLogger: AuthorizationAuditLogger; logger: Logger; }): Promise { - const getSpace = async (): Promise => { - return spaces.spacesService.getActiveSpace(request); + const getSpace = async (): Promise => { + return spaces?.spacesService.getActiveSpace(request); }; // Since we need to do async operations, this static method handles that before creating the Auth class let caseOwners: Set; + try { - const disabledFeatures = new Set((await getSpace()).disabledFeatures ?? []); + const maybeSpace = await getSpace(); + const disabledFeatures = new Set(maybeSpace?.disabledFeatures ?? []); caseOwners = new Set( features diff --git a/x-pack/plugins/cases/server/client/factory.ts b/x-pack/plugins/cases/server/client/factory.ts index b214b40e34701..c12ce99910ac7 100644 --- a/x-pack/plugins/cases/server/client/factory.ts +++ b/x-pack/plugins/cases/server/client/factory.ts @@ -26,6 +26,7 @@ import type { LensServerPluginSetup } from '@kbn/lens-plugin/server'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/server'; import type { NotificationsPluginStart } from '@kbn/notifications-plugin/server'; +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import { SAVED_OBJECT_TYPES } from '../../common/constants'; import { Authorization } from '../authorization/authorization'; import { @@ -49,7 +50,7 @@ import { EmailNotificationService } from '../services/notifications/email_notifi interface CasesClientFactoryArgs { securityPluginSetup: SecurityPluginSetup; securityPluginStart: SecurityPluginStart; - spacesPluginStart: SpacesPluginStart; + spacesPluginStart?: SpacesPluginStart; featuresPluginStart: FeaturesPluginStart; actionsPluginStart: ActionsPluginStart; licensingPluginStart: LicensingPluginStart; @@ -144,7 +145,8 @@ export class CasesClientFactory { externalReferenceAttachmentTypeRegistry: this.options.externalReferenceAttachmentTypeRegistry, securityStartPlugin: this.options.securityPluginStart, publicBaseUrl: this.options.publicBaseUrl, - spaceId: this.options.spacesPluginStart.spacesService.getSpaceId(request), + spaceId: + this.options.spacesPluginStart?.spacesService.getSpaceId(request) ?? DEFAULT_SPACE_ID, savedObjectsSerializer, }); } @@ -197,7 +199,8 @@ export class CasesClientFactory { notifications: this.options.notifications, security: this.options.securityPluginStart, publicBaseUrl: this.options.publicBaseUrl, - spaceId: this.options.spacesPluginStart.spacesService.getSpaceId(request), + spaceId: + this.options.spacesPluginStart?.spacesService.getSpaceId(request) ?? DEFAULT_SPACE_ID, }); return { diff --git a/x-pack/plugins/cases/server/plugin.ts b/x-pack/plugins/cases/server/plugin.ts index ac26cfc7b81a0..bf9033a33552f 100644 --- a/x-pack/plugins/cases/server/plugin.ts +++ b/x-pack/plugins/cases/server/plugin.ts @@ -72,7 +72,7 @@ export interface PluginsStart { licensing: LicensingPluginStart; taskManager?: TaskManagerStartContract; security: SecurityPluginStart; - spaces: SpacesPluginStart; + spaces?: SpacesPluginStart; notifications: NotificationsPluginStart; } 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 937e7449f89c7..2113c116e2787 100644 --- a/x-pack/plugins/cases/server/services/user_profiles/index.ts +++ b/x-pack/plugins/cases/server/services/user_profiles/index.ts @@ -14,6 +14,7 @@ import type { KibanaRequest, Logger } from '@kbn/core/server'; import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import type { UserProfile } from '@kbn/security-plugin/common'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/server'; import { excess, SuggestUserProfilesRequestRt, throwErrors } from '../../../common/api'; @@ -28,7 +29,7 @@ const MIN_PROFILES_SIZE = 0; interface UserProfileOptions { securityPluginSetup: SecurityPluginSetup; securityPluginStart: SecurityPluginStart; - spaces: SpacesPluginStart; + spaces?: SpacesPluginStart; licensingPluginStart: LicensingPluginStart; } @@ -110,7 +111,7 @@ export class UserProfileService { size, owners, securityPluginStart: this.options.securityPluginStart, - spaceId: spaces.spacesService.getSpaceId(request), + spaceId: spaces?.spacesService.getSpaceId(request) ?? DEFAULT_SPACE_ID, }); } catch (error) { throw createCaseError({ From 61bd0c8536776a61a696500b295e97a0b9199b0b Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Thu, 9 Feb 2023 10:53:26 +0100 Subject: [PATCH 005/203] [Enterprise Search] Add order for native connectors (#150463) ## Summary This adds a sort order to native connector configuration entries. Screenshot 2023-02-07 at 18 41 25 --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/connectors/native_connectors.ts | 31 +++++++ .../common/types/connectors.ts | 1 + ..._connector_configuration_api_logic.test.ts | 4 +- ...pdate_connector_configuration_api_logic.ts | 13 ++- .../connector_configuration_config.tsx | 4 +- .../connector_configuration_logic.test.ts | 14 ++-- .../connector_configuration_logic.ts | 82 +++++++++++++------ .../update_connector_configuration.test.ts | 68 +++++++++++++++ .../update_connector_configuration.ts | 40 ++++++--- .../routes/enterprise_search/connectors.ts | 13 +-- 10 files changed, 214 insertions(+), 56 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.test.ts diff --git a/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts b/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts index a19b1e2bb7c19..ad35e96b32f77 100644 --- a/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts +++ b/x-pack/plugins/enterprise_search/common/connectors/native_connectors.ts @@ -19,6 +19,7 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record { it('calls correct api', async () => { const promise = Promise.resolve('result'); http.post.mockReturnValue(promise); - const configuration = { configurationKey: { label: 'hello', value: 'yeahhhh' } }; + const configuration = { configurationKey: 'yeahhhh' }; const result = postConnectorConfiguration({ configuration, connectorId: 'anIndexId', @@ -31,7 +31,7 @@ describe('updateConnectorConfigurationLogic', () => { '/internal/enterprise_search/connectors/anIndexId/configuration', { body: JSON.stringify(configuration) } ); - await expect(result).resolves.toEqual({ configuration, indexName: 'anIndexName' }); + await expect(result).resolves.toEqual({ configuration: 'result', indexName: 'anIndexName' }); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts index 79294d60b5af0..267bd325895b3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_configuration_api_logic.ts @@ -8,11 +8,11 @@ import { i18n } from '@kbn/i18n'; import { ConnectorConfiguration } from '../../../../../common/types/connectors'; -import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { Actions, createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; export interface PostConnectorConfigurationArgs { - configuration: ConnectorConfiguration; + configuration: Record; connectorId: string; indexName: string; } @@ -29,10 +29,10 @@ export const postConnectorConfiguration = async ({ }: PostConnectorConfigurationArgs) => { const route = `/internal/enterprise_search/connectors/${connectorId}/configuration`; - await HttpLogic.values.http.post(route, { + const responseConfig = await HttpLogic.values.http.post(route, { body: JSON.stringify(configuration), }); - return { configuration, indexName }; + return { configuration: responseConfig, indexName }; }; export const ConnectorConfigurationApiLogic = createApiLogic( @@ -46,3 +46,8 @@ export const ConnectorConfigurationApiLogic = createApiLogic( ), } ); + +export type PostConnectorConfigurationActions = Actions< + PostConnectorConfigurationArgs, + PostConnectorConfigurationResponse +>; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx index 00356d85b203f..35914ddb510b7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_config.tsx @@ -30,8 +30,8 @@ export const ConnectorConfigurationConfig: React.FC = ({ children }) => { const { configView, isEditing } = useValues(ConnectorConfigurationLogic); const { setIsEditing } = useActions(ConnectorConfigurationLogic); - const displayList = configView.map(({ label, value }) => ({ - description: value ?? '--', + const displayList = configView.map(({ label, isPasswordField, value }) => ({ + description: isPasswordField && !!value ? '********' : value || '--', title: label, })); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts index 5faf6206a565a..d54604804976b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.test.ts @@ -56,7 +56,7 @@ describe('ConnectorConfigurationLogic', () => { expect(ConnectorConfigurationLogic.values).toEqual({ ...DEFAULT_VALUES, configState: { foo: { label: 'newBar', value: 'oldBar' } }, - configView: [{ key: 'foo', label: 'newBar', value: 'oldBar' }], + configView: [{ isPasswordField: false, key: 'foo', label: 'newBar', value: 'oldBar' }], }); }); it('should set config on setConfigState', () => { @@ -66,7 +66,7 @@ describe('ConnectorConfigurationLogic', () => { expect(ConnectorConfigurationLogic.values).toEqual({ ...DEFAULT_VALUES, configState: { foo: { label: 'thirdBar', value: 'fourthBar' } }, - configView: [{ key: 'foo', label: 'thirdBar', value: 'fourthBar' }], + configView: [{ isPasswordField: false, key: 'foo', label: 'thirdBar', value: 'fourthBar' }], }); }); describe('setLocalConfigEntry', () => { @@ -92,8 +92,8 @@ describe('ConnectorConfigurationLogic', () => { password: { label: 'thirdBar', value: 'fourthBar' }, }, configView: [ - { key: 'bar', label: 'foo', value: 'foofoo' }, - { key: 'password', label: 'thirdBar', value: 'fourthBar' }, + { isPasswordField: false, key: 'bar', label: 'foo', value: 'foofoo' }, + { isPasswordField: true, key: 'password', label: 'thirdBar', value: 'fourthBar' }, ], localConfigState: { bar: { label: 'foo', value: 'fafa' }, @@ -112,7 +112,7 @@ describe('ConnectorConfigurationLogic', () => { expect(ConnectorConfigurationLogic.values).toEqual({ ...DEFAULT_VALUES, configState: connectorIndex.connector.configuration, - configView: [{ key: 'foo', label: 'bar', value: 'barbar' }], + configView: [{ isPasswordField: false, key: 'foo', label: 'bar', value: 'barbar' }], index: connectorIndex, }); }); @@ -134,7 +134,7 @@ describe('ConnectorConfigurationLogic', () => { expect(ConnectorConfigurationLogic.values).toEqual({ ...DEFAULT_VALUES, configState: connectorIndex.connector.configuration, - configView: [{ key: 'foo', label: 'bar', value: 'barbar' }], + configView: [{ isPasswordField: false, key: 'foo', label: 'bar', value: 'barbar' }], index: { ...connectorIndex, connector: { ...connectorIndex.connector, status: ConnectorStatus.NEEDS_CONFIGURATION }, @@ -155,7 +155,7 @@ describe('ConnectorConfigurationLogic', () => { }); ConnectorConfigurationLogic.actions.saveConfig(); expect(ConnectorConfigurationLogic.actions.makeRequest).toHaveBeenCalledWith({ - configuration: { foo: { label: 'bar', value: 'Barbara' } }, + configuration: { foo: 'Barbara' }, connectorId: '2', indexName: 'connector', }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts index dec8044c5c447..5abebb3c1bee5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/connector_configuration_logic.ts @@ -8,12 +8,11 @@ import { kea, MakeLogicType } from 'kea'; import { ConnectorConfiguration, ConnectorStatus } from '../../../../../../common/types/connectors'; -import { Actions } from '../../../../shared/api_logic/create_api_logic'; +import { isNotNullish } from '../../../../../../common/utils/is_not_nullish'; import { ConnectorConfigurationApiLogic, - PostConnectorConfigurationArgs, - PostConnectorConfigurationResponse, + PostConnectorConfigurationActions, } from '../../../api/connector/update_connector_configuration_api_logic'; import { CachedFetchIndexApiLogic, @@ -23,7 +22,7 @@ import { FetchIndexApiResponse } from '../../../api/index/fetch_index_api_logic' import { isConnectorIndex } from '../../../utils/indices'; type ConnectorConfigurationActions = Pick< - Actions, + PostConnectorConfigurationActions, 'apiSuccess' | 'makeRequest' > & { fetchIndexApiSuccess: CachedFetchIndexApiLogicActions['apiSuccess']; @@ -53,9 +52,40 @@ interface ConfigEntry { isPasswordField: boolean; key: string; label: string; + order?: number; value: string; } +/** + * + * Sorts the connector configuration by specified order (if present) + * otherwise by alphabetic order of keys + * + */ +function sortConnectorConfiguration(config: ConnectorConfiguration): ConfigEntry[] { + return Object.keys(config) + .map( + (key) => + ({ + key, + ...config[key], + } as ConfigEntry) + ) + .sort((a, b) => { + if (isNotNullish(a.order)) { + if (isNotNullish(b.order)) { + return a.order - b.order; + } + return -1; + } + if (isNotNullish(b.order)) { + // a doesn't have an order, but b has an order so takes precedence + return 1; + } + return a.key.localeCompare(b.key); + }); +} + export const ConnectorConfigurationLogic = kea< MakeLogicType >({ @@ -117,7 +147,17 @@ export const ConnectorConfigurationLogic = kea< saveConfig: () => { if (isConnectorIndex(values.index)) { actions.makeRequest({ - configuration: values.localConfigState, + configuration: Object.keys(values.localConfigState) + .map((key) => + values.localConfigState[key] + ? { key, value: values.localConfigState[key]?.value ?? '' } + : null + ) + .filter(isNotNullish) + .reduce( + (prev: Record, { key, value }) => ({ ...prev, [key]: value }), + {} + ), connectorId: values.index.connector.id, indexName: values.index.connector.index_name, }); @@ -148,9 +188,9 @@ export const ConnectorConfigurationLogic = kea< localConfigState: [ {}, { - setLocalConfigEntry: (configState, { key, label, value }) => ({ + setLocalConfigEntry: (configState, { key, label, order, value }) => ({ ...configState, - [key]: { label, value }, + [key]: { label, order, value }, }), setLocalConfigState: (_, { configState }) => configState, }, @@ -166,27 +206,21 @@ export const ConnectorConfigurationLogic = kea< selectors: ({ selectors }) => ({ configView: [ () => [selectors.configState], - (configState) => - Object.keys(configState) - .map((key) => ({ - key, - label: configState[key].label, - value: configState[key].value, - })) - .sort((a, b) => a.key.localeCompare(b.key)), + (configState: ConnectorConfiguration) => + sortConnectorConfiguration(configState).map((config) => ({ + ...config, + isPasswordField: + config.key.includes('password') || config.label.toLowerCase().includes('password'), + })), ], localConfigView: [ () => [selectors.localConfigState], (configState) => - Object.keys(configState) - .map((key) => ({ - isPasswordField: - key.includes('password') || configState[key].label.toLowerCase().includes('password'), - key, - label: configState[key].label, - value: configState[key].value, - })) - .sort((a, b) => a.key.localeCompare(b.key)), + sortConnectorConfiguration(configState).map((config) => ({ + ...config, + isPasswordField: + config.key.includes('password') || config.label.toLowerCase().includes('password'), + })), ], }), }); diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.test.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.test.ts new file mode 100644 index 0000000000000..b84be491442cc --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.test.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 { IScopedClusterClient } from '@kbn/core/server'; + +import { CONNECTORS_INDEX } from '../..'; +import { ConnectorStatus } from '../../../common/types/connectors'; + +import { fetchConnectorById } from './fetch_connectors'; +import { updateConnectorConfiguration } from './update_connector_configuration'; + +jest.mock('./fetch_connectors', () => ({ fetchConnectorById: jest.fn() })); + +describe('updateConnectorConfiguration lib function', () => { + const mockClient = { + asCurrentUser: { + update: jest.fn(), + }, + asInternalUser: {}, + }; + + beforeEach(() => { + jest.clearAllMocks(); + (fetchConnectorById as jest.Mock).mockResolvedValue({ + primaryTerm: 0, + seqNo: 3, + value: { + configuration: { test: { label: 'haha', value: 'this' } }, + id: 'connectorId', + status: ConnectorStatus.NEEDS_CONFIGURATION, + }, + }); + }); + + it('should update configuration', async () => { + await expect( + updateConnectorConfiguration(mockClient as unknown as IScopedClusterClient, 'connectorId', { + test: 'newValue', + }) + ).resolves.toEqual({ test: { label: 'haha', value: 'newValue' } }); + expect(mockClient.asCurrentUser.update).toHaveBeenCalledWith({ + doc: { + configuration: { test: { label: 'haha', value: 'newValue' } }, + status: ConnectorStatus.CONFIGURED, + }, + id: 'connectorId', + if_primary_term: 0, + if_seq_no: 3, + index: CONNECTORS_INDEX, + refresh: 'wait_for', + }); + }); + + it('should reject if connector does not exist', async () => { + (fetchConnectorById as jest.Mock).mockImplementation(() => undefined); + + await expect( + updateConnectorConfiguration(mockClient as unknown as IScopedClusterClient, 'connectorId', { + test: 'newValue', + }) + ).rejects.toEqual(new Error('Could not find connector')); + expect(mockClient.asCurrentUser.update).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts index ed1be0c2b6fa8..c19fcb2f01297 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/update_connector_configuration.ts @@ -6,6 +6,7 @@ */ import { IScopedClusterClient } from '@kbn/core/server'; + import { i18n } from '@kbn/i18n'; import { CONNECTORS_INDEX } from '../..'; @@ -15,33 +16,50 @@ import { ConnectorDocument, ConnectorStatus, } from '../../../common/types/connectors'; +import { isNotNullish } from '../../../common/utils/is_not_nullish'; + +import { fetchConnectorById } from './fetch_connectors'; export const updateConnectorConfiguration = async ( client: IScopedClusterClient, connectorId: string, - configuration: ConnectorConfiguration + configuration: Record ) => { - const connectorResult = await client.asCurrentUser.get({ - id: connectorId, - index: CONNECTORS_INDEX, - }); - const connector = connectorResult._source; + const connectorResult = await fetchConnectorById(client, connectorId); + const connector = connectorResult?.value; if (connector) { const status = connector.status === ConnectorStatus.NEEDS_CONFIGURATION ? ConnectorStatus.CONFIGURED : connector.status; - const result = await client.asCurrentUser.index({ - document: { ...connector, configuration, status }, + const updatedConfig = Object.keys(connector.configuration) + .map((key) => + connector.configuration[key] + ? { + ...connector.configuration[key]!, // ugly but needed because typescript refuses to believe this is defined + key, + value: configuration[key] ?? connector.configuration[key]?.value ?? '', + } + : undefined + ) + .filter(isNotNullish) + .reduce((prev: ConnectorConfiguration, curr) => { + const { key, ...config } = curr; + return { ...prev, [curr.key]: config }; + }, {}); + await client.asCurrentUser.update({ + doc: { configuration: updatedConfig, status }, id: connectorId, + if_primary_term: connectorResult?.primaryTerm, + if_seq_no: connectorResult?.seqNo, index: CONNECTORS_INDEX, + refresh: 'wait_for', }); - await client.asCurrentUser.indices.refresh({ index: CONNECTORS_INDEX }); - return result; + return updatedConfig; } else { throw new Error( i18n.translate('xpack.enterpriseSearch.server.connectors.configuration.error', { - defaultMessage: 'Could not find document', + defaultMessage: 'Could not find connector', }) ); } diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts index 8861722205ea0..249a722fa57dd 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts @@ -99,10 +99,7 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) { { path: '/internal/enterprise_search/connectors/{connectorId}/configuration', validate: { - body: schema.recordOf( - schema.string(), - schema.object({ label: schema.string(), value: schema.nullable(schema.string()) }) - ), + body: schema.recordOf(schema.string(), schema.string()), params: schema.object({ connectorId: schema.string(), }), @@ -110,8 +107,12 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) { }, elasticsearchErrorHandler(log, async (context, request, response) => { const { client } = (await context.core).elasticsearch; - await updateConnectorConfiguration(client, request.params.connectorId, request.body); - return response.ok(); + const configuration = await updateConnectorConfiguration( + client, + request.params.connectorId, + request.body + ); + return response.ok({ body: configuration }); }) ); From 876b3f5b3a537b87a0309c7d675003d2efae215a Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Thu, 9 Feb 2023 05:07:26 -0500 Subject: [PATCH 006/203] [Synthetics] fix local params in add monitor and edit monitor (#150602) Resolves https://github.com/elastic/kibana/issues/150599 Resolves https://github.com/elastic/kibana/issues/150597 --- .../components/monitor_add_edit/form/field_config.tsx | 3 ++- .../components/monitor_add_edit/form/form_config.tsx | 2 +- 2 files changed, 3 insertions(+), 2 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 d28f8f7f39eb0..6cb68ae27cd7c 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 @@ -886,8 +886,9 @@ export const FIELD = (readOnly?: boolean): FieldMap => ({ label: i18n.translate('xpack.synthetics.monitorConfig.params.label', { defaultMessage: 'Parameters', }), + controlled: true, component: JSONEditor, - props: ({ setValue }): JSONCodeEditorProps => ({ + props: (): JSONCodeEditorProps => ({ id: 'syntheticsMonitorConfigParams', height: '100px', ariaLabel: i18n.translate('xpack.synthetics.monitorConfig.paramsAria.label', { 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 9c49b0989b5de..f4a099eaa76db 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 @@ -214,7 +214,7 @@ export const FORM_CONFIG = (readOnly: boolean): FieldConfig => ({ FIELD(readOnly)[AlertConfigKey.STATUS_ENABLED], ], step3: [FIELD(readOnly)['source.inline'], FIELD(readOnly)[ConfigKey.PARAMS]], - scriptEdit: [FIELD(readOnly)['source.inline']], + scriptEdit: [FIELD(readOnly)['source.inline'], FIELD(readOnly)[ConfigKey.PARAMS]], advanced: [ { ...DEFAULT_DATA_OPTIONS(readOnly), From 93ec3cdd4016315942cd16b342b1587c399c1d20 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Thu, 9 Feb 2023 10:11:48 +0000 Subject: [PATCH 007/203] [Fleet] Create templates and pipelines when updating package of a single package policy from type integration to input. (#150199) ## Summary Part of #149423 When upgrading a single package policy with conflicts, we use the update package API. When we update from an input package to an integration package, we need to create the per-policy assets. This PR detects if an update is changing from an integration package to an input package and creates the assets as part of the update. I've added an integration test for this scenario. --------- Co-authored-by: Nicolas Chaulet Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../fleet/server/services/package_policy.ts | 43 +++++-- .../fleet_api_integration/apis/epm/get.ts | 2 +- .../integration_to_input/1.0.0/changelog.yml | 6 + .../log/agent/stream/stream.yml.hbs | 9 ++ .../data_stream/log/fields/agent.yml} | Bin 12295 -> 6381 bytes .../data_stream/log/fields/base-fields.yml | 12 ++ .../1.0.0/data_stream/log/manifest.yml | 28 +++++ .../integration_to_input/1.0.0/docs/README.md | 3 + .../integration_to_input/1.0.0/img/icon.svg | 4 + .../integration_to_input/1.0.0/manifest.yml | 24 ++++ .../2.0.0/agent/input/input.yml.hbs | 18 +++ .../integration_to_input/2.0.0/changelog.yml | 11 ++ .../integration_to_input/2.0.0/docs/README.md | 1 + .../2.0.0/fields/input.yml | 4 + .../2.0.0/img/sample-logo.svg | 1 + .../img/sample-screenshot.png} | Bin 30980 -> 18849 bytes .../integration_to_input/2.0.0/manifest.yml | 45 +++++++ .../apis/package_policy/create.ts | 4 +- .../apis/package_policy/update.ts | 111 ++++++++++++++++++ .../apis/package_policy/upgrade.ts | 4 +- 20 files changed, 314 insertions(+), 16 deletions(-) create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/changelog.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/agent/stream/stream.yml.hbs rename x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/{integration_to_input-0.9.0.zip => 1.0.0/data_stream/log/fields/agent.yml} (51%) create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/fields/base-fields.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/manifest.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/docs/README.md create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/img/icon.svg create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/manifest.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/agent/input/input.yml.hbs create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/changelog.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/docs/README.md create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/fields/input.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/img/sample-logo.svg rename x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/{integration_to_input-0.9.1.zip => 2.0.0/img/sample-screenshot.png} (60%) create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/manifest.yml diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index c665d9a6f6f97..5eacf8dd0c3a8 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -513,8 +513,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { esClient: ElasticsearchClient, id: string, packagePolicyUpdate: UpdatePackagePolicy, - options?: { user?: AuthenticatedUser; force?: boolean; skipUniqueNameVerification?: boolean }, - currentVersion?: string + options?: { user?: AuthenticatedUser; force?: boolean; skipUniqueNameVerification?: boolean } ): Promise { let enrichedPackagePolicy: UpdatePackagePolicy; @@ -567,8 +566,9 @@ class PackagePolicyClientImpl implements PackagePolicyClient { inputs = enforceFrozenInputs(oldPackagePolicy.inputs, inputs, options?.force); let elasticsearchPrivileges: NonNullable['privileges']; + let pkgInfo; if (packagePolicy.package?.name) { - const pkgInfo = await getPackageInfo({ + pkgInfo = await getPackageInfo({ savedObjectsClient: soClient, pkgName: packagePolicy.package.name, pkgVersion: packagePolicy.package.version, @@ -609,6 +609,34 @@ class PackagePolicyClientImpl implements PackagePolicyClient { const newPolicy = (await this.get(soClient, id)) as PackagePolicy; + // if we have moved to an input package we need to create the index templates + // for the package policy as input packages create index templates per package policy + if ( + pkgInfo && + pkgInfo.type === 'input' && + oldPackagePolicy.package && + oldPackagePolicy.package?.version !== pkgInfo.version + ) { + if (oldPackagePolicy.package) { + const oldPackage = await getPackageInfo({ + savedObjectsClient: soClient, + pkgName: oldPackagePolicy.package?.name, + pkgVersion: oldPackagePolicy.package?.version, + prerelease: true, + }); + + if (oldPackage.type === 'integration') { + await installAssetsForInputPackagePolicy({ + logger: appContextService.getLogger(), + soClient, + esClient, + pkgInfo, + packagePolicy: newPolicy, + force: true, + }); + } + } + } // Bump revision of associated agent policy const bumpPromise = agentPolicyService.bumpRevision( soClient, @@ -1076,14 +1104,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { ...options, }; - await this.update( - soClient, - esClient, - id, - updatePackagePolicy, - updateOptions, - packagePolicy.package!.version - ); + await this.update(soClient, esClient, id, updatePackagePolicy, updateOptions); // Persist any experimental feature opt-ins that come through the upgrade process to the Installation SO await updateDatastreamExperimentalFeatures( diff --git a/x-pack/test/fleet_api_integration/apis/epm/get.ts b/x-pack/test/fleet_api_integration/apis/epm/get.ts index 7d33b00f54c89..96bd1e01b69b1 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/get.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/get.ts @@ -152,7 +152,7 @@ export default function (providerContext: FtrProviderContext) { // not from the package registry. This is because they contain a field the registry // does not support const res = await supertest - .get(`/api/fleet/epm/packages/integration_to_input/0.9.1?prerelease=true`) + .get(`/api/fleet/epm/packages/integration_to_input/2.0.0`) .expect(200); const packageInfo = res.body.item; diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/changelog.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/changelog.yml new file mode 100644 index 0000000000000..0b37b5572dedf --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: "1.0.0" + changes: + - description: test + type: enhancement + link: http://some.url diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/agent/stream/stream.yml.hbs b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/agent/stream/stream.yml.hbs new file mode 100644 index 0000000000000..371933edee966 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/agent/stream/stream.yml.hbs @@ -0,0 +1,9 @@ +paths: +{{#each paths}} + - {{this}} +{{/each}} + +data_stream: + dataset: {{data_stream.dataset}} + +{{custom}} diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/integration_to_input-0.9.0.zip b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/fields/agent.yml similarity index 51% rename from x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/integration_to_input-0.9.0.zip rename to x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/fields/agent.yml index 4188e89d5b7581bdb89ae6d8d5ae70d897f60469..da4e652c53b8027c4302493bf093a76b6d1b301c 100644 GIT binary patch delta 9 QcmZoqcx$*>f#t0P02O8f;s5{u literal 12295 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 o`Poz_@TZa4I8?qE6sfJ7U3KO+!DqyPW_ diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/fields/base-fields.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/fields/base-fields.yml new file mode 100644 index 0000000000000..7c798f4534ca5 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/fields/base-fields.yml @@ -0,0 +1,12 @@ +- name: data_stream.type + type: constant_keyword + description: Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: Data stream namespace. +- name: '@timestamp' + type: date + description: Event timestamp. diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/manifest.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/manifest.yml new file mode 100644 index 0000000000000..c3d93e36b7cf3 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/data_stream/log/manifest.yml @@ -0,0 +1,28 @@ +title: Log Dataset +type: logs +streams: + - input: logfile + description: Collect your custom log files. + title: Collect log files + vars: + - name: paths + required: true + title: Log file path + description: Path to log files to be collected + type: text + multi: true + - name: data_stream.dataset + required: true + default: generic + title: Dataset name + description: > + Set the name for your dataset. Changing the dataset will send the data to a different index. You can't use `-` in the name of a dataset and only valid characters for [Elasticsearch index names](https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html). + + type: text + - name: custom + title: Custom configurations + description: > + Here YAML configuration options can be used to be added to your configuration. Be careful using this as it might break your configuration file. + + type: yaml + default: "" diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/docs/README.md b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/docs/README.md new file mode 100644 index 0000000000000..ddc05a316388b --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/docs/README.md @@ -0,0 +1,3 @@ +# Log Package + +The log package is used as a generic package based on which any log file can be tailed by adjusting the ingest pipeline. diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/img/icon.svg b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/img/icon.svg new file mode 100644 index 0000000000000..173fdec5072e9 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/img/icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/manifest.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/manifest.yml new file mode 100644 index 0000000000000..4cee11c7c996b --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/1.0.0/manifest.yml @@ -0,0 +1,24 @@ +format_version: 1.0.0 +name: integration_to_input +title: Custom Logs +description: >- + This package goes from an integration package to an input package +type: integration +version: 1.0.0 +release: ga +license: basic +categories: + - custom +policy_templates: + - name: logs + title: Custom logs + description: Collect your custom log files. + inputs: + - type: logfile + title: Custom log file + description: Collect your custom log files. +icons: + - src: "/img/icon.svg" + type: "image/svg+xml" +owner: + github: elastic/elastic-agent-data-plane diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/agent/input/input.yml.hbs b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/agent/input/input.yml.hbs new file mode 100644 index 0000000000000..1ba86fa98a2f8 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/agent/input/input.yml.hbs @@ -0,0 +1,18 @@ +paths: +{{#each paths}} + - {{this}} +{{/each}} + +{{#if tags}} +tags: +{{#each tags as |tag i|}} + - {{tag}} +{{/each}} +{{/if}} + +{{#if pipeline}} +pipeline: {{pipeline}} +{{/if}} + +data_stream: + dataset: {{data_stream.dataset}} \ No newline at end of file diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/changelog.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/changelog.yml new file mode 100644 index 0000000000000..ef016b6ede8fd --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/changelog.yml @@ -0,0 +1,11 @@ +# newer versions go on top +- version: "2.0.0" + changes: + - description: Changed to input pkg + type: enhancement + link: http://some.url +- version: "1.0.0" + changes: + - description: test + type: enhancement + link: http://some.url diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/docs/README.md b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/docs/README.md new file mode 100644 index 0000000000000..9f29c89e0f5ef --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/docs/README.md @@ -0,0 +1 @@ +# Custom Logs \ No newline at end of file diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/fields/input.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/fields/input.yml new file mode 100644 index 0000000000000..f5851c64b6b3a --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/fields/input.yml @@ -0,0 +1,4 @@ +- name: input.name + type: constant_keyword + description: Sample field to be added. + value: logs \ No newline at end of file diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/img/sample-logo.svg b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/img/sample-logo.svg new file mode 100644 index 0000000000000..6268dd88f3b3d --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/img/sample-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/integration_to_input-0.9.1.zip b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/img/sample-screenshot.png similarity index 60% rename from x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/integration_to_input-0.9.1.zip rename to x-pack/test/fleet_api_integration/apis/fixtures/test_packages/integration_to_input/2.0.0/img/sample-screenshot.png index 560755894bfa4f3846812c13baed4c7725ff1345..d7a56a3ecc078c38636698cefba33f86291dd178 100644 GIT binary patch delta 11 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 + This package goes from an integration package to an input package +type: input +version: 2.0.0 +license: basic +categories: + - custom +policy_templates: + - name: logs + type: logs + title: Custom log file + description: Collect your custom log files. + input: logfile + template_path: input.yml.hbs + vars: + - name: paths + type: text + title: Paths + multi: true + required: true + show_user: true + - name: tags + type: text + title: Tags + multi: true + required: true + show_user: false + - name: ignore_older + type: text + title: Ignore events older than + required: false + default: 72h +icons: + - src: "/img/sample-logo.svg" + type: "image/svg+xml" +screenshots: + - src: "/img/sample-screenshot.png" + title: "Sample screenshot" + size: "600x600" + type: "image/png" +owner: + github: elastic/integrations \ No newline at end of file diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts index ed5122d02eb4f..1783a1fc53d09 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts @@ -455,7 +455,7 @@ export default function (providerContext: FtrProviderContext) { policy_id: agentPolicyId, package: { name: 'integration_to_input', - version: '0.9.1', + version: '2.0.0', }, name: 'integration_to_input-1', description: '', @@ -486,7 +486,7 @@ export default function (providerContext: FtrProviderContext) { policy_id: agentPolicyId, package: { name: 'integration_to_input', - version: '0.9.1', + version: '2.0.0', }, name: 'integration_to_input-2', description: '', diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/update.ts b/x-pack/test/fleet_api_integration/apis/package_policy/update.ts index 9c4b35030ced3..2206527667a41 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/update.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/update.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { policyFactory } from '@kbn/security-solution-plugin/common/endpoint/models/policy_config'; import type { NewPackagePolicy } from '@kbn/fleet-plugin/common'; +import { sortBy } from 'lodash'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; import { testUsers } from '../test_users'; @@ -17,12 +18,36 @@ export default function (providerContext: FtrProviderContext) { const dockerServers = getService('dockerServers'); const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); + const es = getService('es'); + + const expectIdArraysEqual = (arr1: any[], arr2: any[]) => { + expect(sortBy(arr1, 'id')).to.eql(sortBy(arr2, 'id')); + }; + + const getInstallationSavedObject = async (name: string, version: string) => { + const res = await supertest.get(`/api/fleet/epm/packages/${name}-${version}`).expect(200); + return res.body.item.savedObject.attributes; + }; const getPackagePolicyById = async (id: string) => { const { body } = await supertest.get(`/api/fleet/package_policies/${id}`); return body; }; + const getComponentTemplate = async (name: string) => { + try { + const { component_templates: templates } = await es.cluster.getComponentTemplate({ name }); + + return templates?.[0] || null; + } catch (e) { + if (e.statusCode === 404) { + return null; + } + + throw e; + } + }; + const server = dockerServers.get('registry'); // use function () {} and not () => {} here // because `this` has to point to the Mocha context @@ -504,5 +529,91 @@ export default function (providerContext: FtrProviderContext) { ); }); }); + + describe('Input Packages', () => { + it('should install index templates when upgrading from input package to integration package', async () => { + const { body: packagePolicyResponse } = await supertest + .post(`/api/fleet/package_policies`) + .set('kbn-xsrf', 'xxxx') + .send({ + policy_id: agentPolicyId, + force: true, + package: { + name: 'integration_to_input', + version: '1.0.0', + }, + name: 'integration_to_input-1', + description: '', + namespace: 'default', + inputs: { + 'logs-logfile': { + enabled: true, + streams: { + 'integration_to_input.log': { + enabled: true, + vars: { + paths: ['/tmp/test.log'], + 'data_stream.dataset': 'somedataset', + custom: '', + }, + }, + }, + }, + }, + }); + + const inputPackagePolicyId = packagePolicyResponse.item.id; + + await supertest + .put(`/api/fleet/package_policies/${inputPackagePolicyId}`) + .set('kbn-xsrf', 'xxxx') + .send({ + package: { + name: 'integration_to_input', + version: '2.0.0', + experimental_data_stream_features: [], + }, + name: 'integration_to_input-1', + namespace: 'default', + description: '', + policy_id: agentPolicyId, + vars: {}, + inputs: { + 'logs-logfile': { + enabled: true, + streams: { + 'integration_to_input.logs': { + enabled: true, + vars: { + paths: ['/tmp/test.log'], + 'data_stream.dataset': 'somedataset', + tags: ['tag1'], + ignore_older: '72h', + }, + }, + }, + }, + }, + }) + .expect(200); + + const installation = await getInstallationSavedObject('integration_to_input', '2.0.0'); + expectIdArraysEqual(installation.installed_es, [ + // assets from version 1.0.0 + { id: 'logs-integration_to_input.log', type: 'index_template' }, + { id: 'logs-integration_to_input.log-1.0.0', type: 'ingest_pipeline' }, + { id: 'logs-integration_to_input.log@custom', type: 'component_template' }, + { id: 'logs-integration_to_input.log@package', type: 'component_template' }, + // assets from version 2.0.0 for new package policy + { id: 'logs-somedataset-2.0.0', type: 'ingest_pipeline' }, + { id: 'logs-somedataset', type: 'index_template' }, + { id: 'logs-somedataset@package', type: 'component_template' }, + { id: 'logs-somedataset@custom', type: 'component_template' }, + ]); + + const dataset3PkgComponentTemplate = await getComponentTemplate('logs-somedataset@package'); + expect(dataset3PkgComponentTemplate).not.to.be(null); + }); + }); }); } diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts b/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts index 361f75fc9d369..bad75e9746e6a 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/upgrade.ts @@ -1141,7 +1141,7 @@ export default function (providerContext: FtrProviderContext) { }); describe('when upgrading from an integration package to an input package where a required variable has been added', function () { - withTestPackage('integration_to_input', '0.9.1'); + withTestPackage('integration_to_input', '2.0.0'); beforeEach(async function () { const { body: agentPolicyResponse } = await supertest @@ -1162,7 +1162,7 @@ export default function (providerContext: FtrProviderContext) { policy_id: agentPolicyId, package: { name: 'integration_to_input', - version: '0.9.0', + version: '1.0.0', }, name: 'integration_to_input-1', description: '', From 94085525a9233423d7b3b0164b56c6213078f20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Thu, 9 Feb 2023 11:23:20 +0100 Subject: [PATCH 008/203] [SO PIT Finder] Ensure mandatory sort fields (#150574) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Resolves https://github.com/elastic/kibana/issues/150310 --- .../src/lib/point_in_time_finder.test.ts | 46 +++++++++++++++++++ .../src/lib/point_in_time_finder.ts | 6 +-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.test.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.test.ts index fe8b8190ff840..a2b4121cebad0 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.test.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.test.ts @@ -235,6 +235,52 @@ describe('createPointInTimeFinder()', () => { ); }); + test('still applies the defaults in the mandatory fields even when `undefined` is explicitly provided', async () => { + repository.openPointInTimeForType.mockResolvedValueOnce({ + id: 'abc123', + }); + repository.find.mockResolvedValueOnce({ + total: 2, + saved_objects: mockHits, + pit_id: 'abc123', + per_page: 2, + page: 0, + }); + + const findOptions: SavedObjectsCreatePointInTimeFinderOptions = { + type: ['visualization'], + search: 'foo*', + // Intentionally trying to remove the sort fields + sortField: undefined, + sortOrder: undefined, + }; + + const internalOptions = {}; + const finder = new PointInTimeFinder(findOptions, { + logger, + client: repository, + internalOptions, + }); + const hits: SavedObjectsFindResult[] = []; + for await (const result of finder.find()) { + hits.push(...result.saved_objects); + } + + expect(hits.length).toBe(2); + expect(repository.openPointInTimeForType).toHaveBeenCalledTimes(1); + expect(repository.closePointInTime).toHaveBeenCalledTimes(1); + expect(repository.find).toHaveBeenCalledTimes(1); + expect(repository.find).toHaveBeenCalledWith( + expect.objectContaining({ + pit: expect.objectContaining({ id: 'abc123', keepAlive: '2m' }), + sortField: 'updated_at', + sortOrder: 'desc', + type: ['visualization'], + }), + internalOptions + ); + }); + describe('#close', () => { test('calls closePointInTime with correct ID', async () => { repository.openPointInTimeForType.mockResolvedValueOnce({ diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.ts index 834a64552a1ec..524b571894007 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/lib/point_in_time_finder.ts @@ -147,14 +147,14 @@ export class PointInTimeFinder try { return await this.#client.find( { + ...findOptions, // Sort fields are required to use searchAfter, so we set some defaults here - sortField: 'updated_at', - sortOrder: 'desc', + sortField: findOptions.sortField ?? 'updated_at', + sortOrder: findOptions.sortOrder ?? 'desc', // Bump keep_alive by 2m on every new request to allow for the ES client // to make multiple retries in the event of a network failure. pit: id ? { id, keepAlive: '2m' } : undefined, searchAfter, - ...findOptions, }, this.#internalOptions ); From 57c828b8bfe7d447868ddd150cc0528b877cddf3 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:23:59 +0100 Subject: [PATCH 009/203] [Fleet] fixed icon for bulk diagnostics (#150545) ## Summary Closes https://github.com/elastic/kibana/issues/150536 image Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../sections/agents/agent_list_page/components/bulk_actions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/bulk_actions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/bulk_actions.tsx index cd00ba7f14bb0..5b0129fe8c2d9 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/bulk_actions.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/bulk_actions.tsx @@ -183,7 +183,7 @@ export const AgentBulkActions: React.FunctionComponent = ({ }} /> ), - icon: , + icon: , disabled: !atLeastOneActiveAgentSelected, onClick: () => { closeMenu(); From dadea40c862f2f1dff8e5984fafdca41b0714345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Thu, 9 Feb 2023 11:45:16 +0100 Subject: [PATCH 010/203] [APM] Overwrite sourcemap if it already exists (#150533) Related: https://github.com/elastic/kibana/pull/147208 This changes the behaviour of APM managed source maps. Currently when uploading a sourcemap with a `service.name`, `service.version` and `path` that already exists the new source map will be ignored. With the new behaviour the existing source map will be overwritten by the new one. @simitt --- .../source_maps/create_apm_source_map.ts | 22 ++--- .../tests/sourcemaps/sourcemaps.ts | 88 ++++++++++++++++--- 2 files changed, 85 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts b/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts index f4a49d475ceef..442b9299587a6 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/create_apm_source_map.ts @@ -6,7 +6,6 @@ */ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { isElasticsearchVersionConflictError } from '@kbn/fleet-plugin/server/errors/utils'; import { Logger } from '@kbn/core/server'; import { APM_SOURCE_MAP_INDEX } from '../settings/apm_indices/get_apm_indices'; import { ApmSourceMap } from './create_apm_source_map_index_template'; @@ -44,18 +43,11 @@ export async function createApmSourceMap({ service: { name: serviceName, version: serviceVersion }, }; - try { - const id = getSourceMapId({ serviceName, serviceVersion, bundleFilepath }); - logger.debug(`Create APM source map: "${id}"`); - return await internalESClient.create({ - index: APM_SOURCE_MAP_INDEX, - id, - body: doc, - }); - } catch (e) { - // we ignore 409 errors from the create (document already exists) - if (!isElasticsearchVersionConflictError(e)) { - throw e; - } - } + const id = getSourceMapId({ serviceName, serviceVersion, bundleFilepath }); + logger.debug(`Create APM source map: "${id}"`); + return await internalESClient.index({ + index: APM_SOURCE_MAP_INDEX, + id, + body: doc, + }); } diff --git a/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts b/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts index bd7368c59afe3..a918e982f5634 100644 --- a/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts +++ b/x-pack/test/apm_api_integration/tests/sourcemaps/sourcemaps.ts @@ -4,14 +4,19 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { unzip as unzipAsyncCallback } from 'zlib'; import pRetry from 'p-retry'; import type { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; import type { ApmSourceMap } from '@kbn/apm-plugin/server/routes/source_maps/create_apm_source_map_index_template'; import type { SourceMap } from '@kbn/apm-plugin/server/routes/source_maps/route'; import expect from '@kbn/expect'; import { first, last, times } from 'lodash'; +import { promisify } from 'util'; +import { GetResponse } from '@elastic/elasticsearch/lib/api/types'; import { FtrProviderContext } from '../../common/ftr_provider_context'; +const unzip = promisify(unzipAsyncCallback); + const SAMPLE_SOURCEMAP = { version: 3, file: 'out.js', @@ -118,10 +123,19 @@ export default function ApiTest({ getService }: FtrProviderContext) { } registry.when('source maps', { config: 'basic', archives: [] }, () => { + // ensure clean state before starting before(async () => { await Promise.all([deleteAllFleetSourceMaps(), deleteAllApmSourceMaps()]); }); + async function getDecodedSourceMapContent( + encodedContent?: string + ): Promise { + if (encodedContent) { + return JSON.parse((await unzip(Buffer.from(encodedContent, 'base64'))).toString()); + } + } + let resp: APIReturnType<'POST /api/apm/sourcemaps'>; describe('upload source map', () => { after(async () => { @@ -158,20 +172,74 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); it('is added to .apm-source-map index', async () => { - const res = await esClient.search({ + const res = await esClient.search({ index: '.apm-source-map', }); - const doc = res.hits.hits[0]._source as ApmSourceMap; - expect(doc.content).to.be( - 'eJyrVipLLSrOzM9TsjI0MtZRKs4vLUpOLVayilZSitVRyk0sKMjMSwfylZRqAURLDgo=' - ); - expect(doc.content_sha256).to.be( - '02dd950aa88a66183d312a7a5f44d72fc9e3914cdbbe5e3a04f1509a8a3d7d83' + const source = res.hits.hits[0]._source; + const decodedSourceMap = await getDecodedSourceMapContent(source?.content); + expect(decodedSourceMap).to.eql(SAMPLE_SOURCEMAP); + expect(source?.content_sha256).to.be( + 'bfc4a5793a604af28edb8536f7f9b56658a4ccab3db74676c77f850f0b9e2c28' ); - expect(doc.file.path).to.be('bar'); - expect(doc.service.name).to.be('uploading-test'); - expect(doc.service.version).to.be('1.0.0'); + expect(source?.file.path).to.be('bar'); + expect(source?.service.name).to.be('uploading-test'); + expect(source?.service.version).to.be('1.0.0'); + }); + + describe('when uploading a new source map with the same service.name, service.version and path', () => { + let resBefore: GetResponse; + let resAfter: GetResponse; + + before(async () => { + async function getSourceMapDocFromApmIndex() { + await esClient.indices.refresh({ index: '.apm-source-map' }); + return await esClient.get({ + index: '.apm-source-map', + id: 'uploading-test-1.0.0-bar', + }); + } + + resBefore = await getSourceMapDocFromApmIndex(); + + await uploadSourcemap({ + serviceName: 'uploading-test', + serviceVersion: '1.0.0', + bundleFilePath: 'bar', + sourcemap: { ...SAMPLE_SOURCEMAP, sourceRoot: 'changed-source-root' }, + }); + + resAfter = await getSourceMapDocFromApmIndex(); + }); + + after(async () => { + await deleteAllApmSourceMaps(); + await deleteAllFleetSourceMaps(); + }); + + it('creates one document in the .apm-source-map index', async () => { + const res = await esClient.search({ index: '.apm-source-map', size: 0 }); + + // @ts-expect-error + expect(res.hits.total.value).to.be(1); + }); + + it('creates two documents in the .fleet-artifacts index', async () => { + const res = await listSourcemaps({ page: 1, perPage: 10 }); + expect(res.total).to.be(2); + }); + + it('updates the content', async () => { + const contentBefore = await getDecodedSourceMapContent(resBefore._source?.content); + const contentAfter = await getDecodedSourceMapContent(resAfter._source?.content); + + expect(contentBefore?.sourceRoot).to.be(''); + expect(contentAfter?.sourceRoot).to.be('changed-source-root'); + }); + + it('updates the content hash', async () => { + expect(resBefore._source?.content_sha256).to.not.be(resAfter._source?.content_sha256); + }); }); }); From 111d9d1f87a726f6f2561b9e29538b6db73df208 Mon Sep 17 00:00:00 2001 From: Rudolf Meijering Date: Thu, 9 Feb 2023 12:14:12 +0100 Subject: [PATCH 011/203] Cleanup `enabled: false` saved objects mappings (#149102) ## Summary Clean up saved object mappings to reduce the field count and make mappings more future-proof. This PR attempts to remove all `enabled: false` mappings. It's not possible to toggle the `enabled` property so it becomes impossible to ever query over a disabled field. `type: 'object', enabled: 'false'` also provides worse validation since it's possible to index a string into such an object. So using `dynamic: false, properties: {}` provides better validation and is more future-proof allowing us to query over these fields should the need arise. Since these fields can't be queried over it should be safe to remove these mappings but please review and/or test to ensure there's no regressions. If your plugin every relied on the lack of validation for being able to ingest a `string` field into an `type: 'object', enabled: 'false'` field this PR would now cause failures. Related: https://github.com/elastic/dev/issues/2189 ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- ...grations_state_action_machine.test.ts.snap | 30 ++++++++++ .../src/core/unused_types.ts | 2 + .../src/initial_state.test.ts | 5 ++ .../migrations/7.7.2_xpack_100k.test.ts | 2 +- .../migrations/check_registered_types.test.ts | 23 ++++---- .../data/server/saved_objects/query.ts | 7 ++- .../search/saved_objects/search_session.ts | 12 ++-- .../server/saved_objects/search.ts | 2 +- .../alerting/server/saved_objects/mappings.ts | 4 +- .../server/saved_object_types/comments.ts | 6 +- .../fleet/server/saved_objects/index.ts | 55 ++++--------------- .../saved_objects/setup_saved_objects.ts | 17 ------ .../lib/saved_query/saved_object_mappings.ts | 20 +++---- .../legacy_saved_object_mappings.ts | 4 +- 14 files changed, 87 insertions(+), 102 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap index 28d12601d23f3..6973b0b8a7081 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/__snapshots__/migrations_state_action_machine.test.ts.snap @@ -81,6 +81,11 @@ Object { "type": "guided-setup-state", }, }, + Object { + "term": Object { + "type": "maps-telemetry", + }, + }, Object { "term": Object { "type": "ml-telemetry", @@ -272,6 +277,11 @@ Object { "type": "guided-setup-state", }, }, + Object { + "term": Object { + "type": "maps-telemetry", + }, + }, Object { "term": Object { "type": "ml-telemetry", @@ -467,6 +477,11 @@ Object { "type": "guided-setup-state", }, }, + Object { + "term": Object { + "type": "maps-telemetry", + }, + }, Object { "term": Object { "type": "ml-telemetry", @@ -666,6 +681,11 @@ Object { "type": "guided-setup-state", }, }, + Object { + "term": Object { + "type": "maps-telemetry", + }, + }, Object { "term": Object { "type": "ml-telemetry", @@ -907,6 +927,11 @@ Object { "type": "guided-setup-state", }, }, + Object { + "term": Object { + "type": "maps-telemetry", + }, + }, Object { "term": Object { "type": "ml-telemetry", @@ -1109,6 +1134,11 @@ Object { "type": "guided-setup-state", }, }, + Object { + "term": Object { + "type": "maps-telemetry", + }, + }, Object { "term": Object { "type": "ml-telemetry", diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts index 3f46404066383..e506ff40073fc 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/unused_types.ts @@ -41,6 +41,8 @@ export const REMOVED_TYPES: string[] = [ 'ui-counter', // Deprecated, no longer used since 7.13 https://github.com/elastic/kibana/pull/94923/files 'application_usage_transactional', + // Removed in 7.8.1 / 7.9.0 https://github.com/elastic/kibana/pull/69871 + 'maps-telemetry', // Deprecated, no longer used since 8.7 https://github.com/elastic/kibana/pull/148530 'csp_rule', ].sort(); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts index 8a66bac6ce9fe..27798706e8fd1 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/initial_state.test.ts @@ -118,6 +118,11 @@ describe('createInitialState', () => { "type": "guided-setup-state", }, }, + Object { + "term": Object { + "type": "maps-telemetry", + }, + }, Object { "term": Object { "type": "ml-telemetry", diff --git a/src/core/server/integration_tests/saved_objects/migrations/7.7.2_xpack_100k.test.ts b/src/core/server/integration_tests/saved_objects/migrations/7.7.2_xpack_100k.test.ts index a90291d1614a4..4922223015904 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/7.7.2_xpack_100k.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/7.7.2_xpack_100k.test.ts @@ -29,7 +29,7 @@ async function removeLogFile() { } /** Number of SO documents dropped during the migration because they belong to an unused type */ -const UNUSED_SO_COUNT = 4; +const UNUSED_SO_COUNT = 5; describe('migration from 7.7.2-xpack with 100k objects', () => { let esServer: TestElasticsearchUtils; diff --git a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts index d5f7c58abc07f..5558e5156324d 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/check_registered_types.test.ts @@ -57,7 +57,7 @@ describe('checking migration metadata changes on all registered SO types', () => Object { "action": "6cfc277ed3211639e37546ac625f4a68f2494215", "action_task_params": "db2afea7d78e00e725486b791554d0d4e81956ef", - "alert": "492f749af60bed1cc7022519ddf5fe4c482b62c4", + "alert": "f81ad957a7936522482e4539c7a96a963ebdbc3e", "api_key_pending_invalidation": "16e7bcf8e78764102d7f525542d5b616809a21ee", "apm-indices": "d19dd7fb51f2d2cbc1f8769481721e0953f9a6d2", "apm-server-schema": "1d42f17eff9ec6c16d3a9324d9539e2d123d0a9a", @@ -70,7 +70,7 @@ describe('checking migration metadata changes on all registered SO types', () => "canvas-workpad": "ab0525bd5aa4dbad2d6fdb30e6a51bb475254751", "canvas-workpad-template": "c54f2a188a1d0bf18a6cebd9d6f28a7337d41bbf", "cases": "74c00dfb25f4b109894971bd1090fce4a7c99490", - "cases-comments": "b94072c8f0cb642dd6da43c833bd2d391e175ec0", + "cases-comments": "371662a8464e623f1f4f55a981cec78bec4a12f5", "cases-configure": "25099c9e4bbb91e01e334848c605b4a5de5c9fce", "cases-connector-mappings": "8de3b77dc6ae8ee62cce2b58a222471dfc3dbdad", "cases-telemetry": "fdeddcef28c75d8c66422475a829e75d37f0b668", @@ -84,7 +84,7 @@ describe('checking migration metadata changes on all registered SO types', () => "endpoint:user-artifact": "a5b154962fb6cdf5d9e7452e58690054c95cc72a", "endpoint:user-artifact-manifest": "5989989c0f84dd2d02da1eb46b6254e334bd2ccd", "enterprise_search_telemetry": "4b41830e3b28a16eb92dee0736b44ae6276ced9b", - "epm-packages": "1922a722ea42ab4953a96037fabb81a9ded8e240", + "epm-packages": "83235af7c95fd9bfb1d70996a5511e05b3fcc9ef", "epm-packages-assets": "00c8b5e5bf059627ffc9fbde920e1ac75926c5f6", "event_loop_delays_daily": "ef49e7f15649b551b458c7ea170f3ed17f89abd0", "exception-list": "38181294f64fc406c15f20d85ca306c8a4feb3c0", @@ -104,7 +104,7 @@ describe('checking migration metadata changes on all registered SO types', () => "ingest-agent-policies": "e5bb18f8c1d1106139e82fccb93fce01b21fde9b", "ingest-download-sources": "95a15b6589ef46e75aca8f7e534c493f99cc3ccd", "ingest-outputs": "f5adeb3f6abc732a6067137e170578dbf1f58c62", - "ingest-package-policies": "f20a00d14ba0651e0dbdada40f9762926819e298", + "ingest-package-policies": "98a5f5defe00d606bfaa64f80bd745ff1465df18", "ingest_manager_settings": "fb75bff08a8de3435b23664b1191f9244a255701", "inventory-view": "6d47ef0b38166ecbd1c2fc7394599a4500db1ae4", "kql-telemetry": "23ed96ff02cd69cbfaa22f313cae3a54c434db51", @@ -112,25 +112,24 @@ describe('checking migration metadata changes on all registered SO types', () => "lens": "42793535312de4e3e3df16a69cb85f5df3b14f72", "lens-ui-telemetry": "d6c4e330d170eefc6214dbf77a53de913fa3eebc", "map": "7902b2e2a550e0b73fd5aa6c4e2ba3a4e6558877", - "maps-telemetry": "1b2e468ec4dd1207e417b98f84b24cd87e1efd14", "metrics-explorer-view": "713dbf1ab5e067791d19170f715eb82cf07ebbcc", "ml-job": "12e21f1b1adfcc1052dc0b10c7459de875653b94", "ml-module": "c88b6a012cfb7b7adb7629b1edeab6b83f1fd048", "ml-trained-model": "49a1685d79990ad05ea1d1d30e28456fe002f3b9", "monitoring-telemetry": "24f7393dfacb6c7b0f7ad7d242171a1c29feaa48", "osquery-manager-usage-metric": "23a8f08a98dd0f58ab4e559daa35b06edc40ed4f", - "osquery-pack": "407f82b8f05f02a04627993e6d2a071b4d71f816", - "osquery-pack-asset": "e10ca4b6ac5dff1954b5140ed97c3187d353a029", - "osquery-saved-query": "86bd3e1d39c470375263b28437c67b4f96667bc2", - "query": "495b96d251383d44b48ad3ccd831b857f909ae41", + "osquery-pack": "edd84b2c59ef36214ece0676706da8f22175c660", + "osquery-pack-asset": "18e08979d46ee7e5538f54c080aec4d8c58516ca", + "osquery-saved-query": "f5e4e303f65c7607248ea8b2672f1ee30e4fb15e", + "query": "f94de164936da788e9215c0e9b824f8b948ea859", "rules-settings": "9854495c3b54b16a6625fb250c35e5504da72266", "sample-data-telemetry": "c38daf1a49ed24f2a4fb091e6e1e833fccf19935", - "search": "928589cf4b2497623faa48d22f406bab4721704c", - "search-session": "e0f495ac1b3bb40ba3eb3aea90b2d11e6c8d4c32", + "search": "01bc42d635e9ea0588741c4c7a2bbd3feb3ac5dc", + "search-session": "5f40f6101fc2ec8ce5210d735ea2e00a87c02886", "search-telemetry": "ab67ef721f294f28d5e10febbd20653347720188", "security-rule": "1ff82dfb2298c3caf6888fc3ef15c6bf7a628877", "security-solution-signals-migration": "c2db409c1857d330beb3d6fd188fa186f920302c", - "siem-detection-engine-rule-actions": "dbf3747aad2b986534b052703063a7026b25f485", + "siem-detection-engine-rule-actions": "123c130dc38120a470d8db9fed9a4cebd2046445", "siem-ui-timeline": "e9d6b3a9fd7af6dc502293c21cbdb309409f3996", "siem-ui-timeline-note": "13c9d4c142f96624a93a623c6d7cba7e1ae9b5a6", "siem-ui-timeline-pinned-event": "96a43d59b9e2fc11f12255a0cb47ef0a3d83af4c", diff --git a/src/plugins/data/server/saved_objects/query.ts b/src/plugins/data/server/saved_objects/query.ts index 3c7e964d6c863..0e11bf7a9f2e0 100644 --- a/src/plugins/data/server/saved_objects/query.ts +++ b/src/plugins/data/server/saved_objects/query.ts @@ -35,8 +35,11 @@ export const querySavedObjectType: SavedObjectsType = { query: { properties: { language: { type: 'keyword' }, query: { type: 'keyword', index: false } }, }, - filters: { type: 'object', enabled: false }, - timefilter: { type: 'object', enabled: false }, + filters: { + dynamic: false, + properties: {}, + }, + timefilter: { dynamic: false, properties: {} }, }, }, migrations: savedQueryMigrations, diff --git a/src/plugins/data/server/search/saved_objects/search_session.ts b/src/plugins/data/server/search/saved_objects/search_session.ts index 3eb1c6190dd6e..5e3906cfd8f63 100644 --- a/src/plugins/data/server/search/saved_objects/search_session.ts +++ b/src/plugins/data/server/search/saved_objects/search_session.ts @@ -35,16 +35,16 @@ export const searchSessionSavedObjectType: SavedObjectsType = { type: 'keyword', }, initialState: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, restoreState: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, idMapping: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, realmType: { type: 'keyword', diff --git a/src/plugins/saved_search/server/saved_objects/search.ts b/src/plugins/saved_search/server/saved_objects/search.ts index 5960cd8ebdbe9..83923df21480f 100644 --- a/src/plugins/saved_search/server/saved_objects/search.ts +++ b/src/plugins/saved_search/server/saved_objects/search.ts @@ -49,7 +49,7 @@ export function getSavedSearchObjectType( }, sort: { type: 'keyword', index: false, doc_values: false }, title: { type: 'text' }, - grid: { type: 'object', enabled: false }, + grid: { dynamic: false, properties: {} }, version: { type: 'integer' }, rowHeight: { type: 'text' }, timeRestore: { type: 'boolean', index: false, doc_values: false }, diff --git a/x-pack/plugins/alerting/server/saved_objects/mappings.ts b/x-pack/plugins/alerting/server/saved_objects/mappings.ts index 75c3185db7ef4..be70255f18840 100644 --- a/x-pack/plugins/alerting/server/saved_objects/mappings.ts +++ b/x-pack/plugins/alerting/server/saved_objects/mappings.ts @@ -53,8 +53,8 @@ export const alertMappings: SavedObjectsTypeMappingDefinition = { type: 'keyword', }, params: { - enabled: false, - type: 'object', + dynamic: false, + properties: {}, }, frequency: { properties: { diff --git a/x-pack/plugins/cases/server/saved_object_types/comments.ts b/x-pack/plugins/cases/server/saved_object_types/comments.ts index 95df2007da00b..c795b7d960e61 100644 --- a/x-pack/plugins/cases/server/saved_object_types/comments.ts +++ b/x-pack/plugins/cases/server/saved_object_types/comments.ts @@ -84,16 +84,14 @@ export const createCaseCommentSavedObjectType = ({ }, externalReferenceMetadata: { dynamic: false, - type: 'object', - enabled: false, + properties: {}, }, persistableStateAttachmentTypeId: { type: 'keyword', }, persistableStateAttachmentState: { dynamic: false, - type: 'object', - enabled: false, + properties: {}, }, pushed_at: { type: 'date', diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index cd4ff53f86d46..1a8178890b1dc 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -184,48 +184,13 @@ const getSavedObjectTypes = ( }, }, elasticsearch: { - enabled: false, - properties: { - privileges: { - properties: { - cluster: { type: 'keyword' }, - }, - }, - }, + dynamic: false, + properties: {}, }, vars: { type: 'flattened' }, inputs: { - type: 'nested', - enabled: false, - properties: { - type: { type: 'keyword' }, - policy_template: { type: 'keyword' }, - enabled: { type: 'boolean' }, - vars: { type: 'flattened' }, - config: { type: 'flattened' }, - compiled_input: { type: 'flattened' }, - streams: { - type: 'nested', - properties: { - id: { type: 'keyword' }, - enabled: { type: 'boolean' }, - data_stream: { - properties: { - dataset: { type: 'keyword' }, - type: { type: 'keyword' }, - elasticsearch: { - properties: { - privileges: { type: 'flattened' }, - }, - }, - }, - }, - vars: { type: 'flattened' }, - config: { type: 'flattened' }, - compiled_stream: { type: 'flattened' }, - }, - }, - }, + dynamic: false, + properties: {}, }, revision: { type: 'integer' }, updated_at: { type: 'date' }, @@ -264,8 +229,8 @@ const getSavedObjectTypes = ( internal: { type: 'boolean' }, keep_policies_up_to_date: { type: 'boolean', index: false }, es_index_patterns: { - enabled: false, - type: 'object', + dynamic: false, + properties: {}, }, verification_status: { type: 'keyword' }, verification_key_id: { type: 'keyword' }, @@ -278,13 +243,13 @@ const getSavedObjectTypes = ( }, }, installed_kibana: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, installed_kibana_space_id: { type: 'keyword' }, package_assets: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, install_started_at: { type: 'date' }, install_version: { type: 'keyword' }, 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 c75f1f322e25c..126ec9851c905 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 @@ -61,23 +61,6 @@ export function setupSavedObjects( ); }, }); - - /* - * The maps-telemetry saved object type isn't used, but in order to remove these fields from - * the mappings we register this type with `type: 'object', enabled: true` to remove all - * previous fields from the mappings until https://github.com/elastic/kibana/issues/67086 is - * solved. - */ - core.savedObjects.registerType({ - name: 'maps-telemetry', - hidden: false, - namespaceType: 'agnostic', - mappings: { - // @ts-ignore Core types don't support this since it's only really valid when removing a previously registered type - type: 'object', - enabled: false, - }, - }); } /** diff --git a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts index f0c04848aa52f..f3bc667513609 100644 --- a/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts +++ b/x-pack/plugins/osquery/server/lib/saved_query/saved_object_mappings.ts @@ -66,8 +66,8 @@ export const savedQuerySavedObjectMappings: SavedObjectsType['mappings'] = { type: 'keyword', }, ecs_mapping: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, }, }; @@ -124,8 +124,8 @@ export const packSavedObjectMappings: SavedObjectsType['mappings'] = { type: 'boolean', }, shards: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, version: { type: 'long', @@ -149,8 +149,8 @@ export const packSavedObjectMappings: SavedObjectsType['mappings'] = { type: 'keyword', }, ecs_mapping: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, }, }, @@ -200,8 +200,8 @@ export const packAssetSavedObjectMappings: SavedObjectsType['mappings'] = { type: 'long', }, shards: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, queries: { dynamic: false, @@ -222,8 +222,8 @@ export const packAssetSavedObjectMappings: SavedObjectsType['mappings'] = { type: 'keyword', }, ecs_mapping: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, }, }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_saved_object_mappings.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_saved_object_mappings.ts index 26daac60ffc23..1868cb238b11e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_saved_object_mappings.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/rule_actions/legacy_saved_object_mappings.ts @@ -44,8 +44,8 @@ const legacyRuleActionsSavedObjectMappings: SavedObjectsType['mappings'] = { type: 'keyword', }, params: { - type: 'object', - enabled: false, + dynamic: false, + properties: {}, }, }, }, From 381b82052f76c8148e025f0b85fba5aa2b7a3529 Mon Sep 17 00:00:00 2001 From: Coen Warmer Date: Thu, 9 Feb 2023 12:18:15 +0100 Subject: [PATCH 012/203] Update comment to point people in the right direction when searching for collected metrics (#150582) ## Summary This updates the comments for the `use_track_metric` hooks to guide users to find where the collected data ends up. --- .../plugins/observability/public/hooks/use_track_metric.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability/public/hooks/use_track_metric.tsx b/x-pack/plugins/observability/public/hooks/use_track_metric.tsx index 6a3f0c3e8965d..7138c20ef6aa6 100644 --- a/x-pack/plugins/observability/public/hooks/use_track_metric.tsx +++ b/x-pack/plugins/observability/public/hooks/use_track_metric.tsx @@ -13,10 +13,8 @@ import { ObservabilityApp } from '../../typings/common'; /** * Note: The usage_collection plugin will take care of sending this data to the telemetry server. - * You can find these metrics stored at: - * stack_stats.kibana.plugins.ui_metric.{app}.{metric}(__delayed_{n}ms)? - * which will be an array of objects each containing a key, representing the metric, and - * a value, which will be a counter + * You can find the metrics that are collected by these hooks in Stack Telemetry. + * Search the index `kibana-ui-counter`. You can filter for `eventName` and/or `appName`. */ interface TrackOptions { From 5f0b56d3bc470eba4753dfa806154814609deee0 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Thu, 9 Feb 2023 12:21:32 +0100 Subject: [PATCH 013/203] [@kbn/handlebars] Minor refactor (#150440) --- packages/kbn-handlebars/index.test.ts | 7 +-- .../kbn-handlebars/src/__jest__/test_bench.ts | 43 ++++++++----------- packages/kbn-handlebars/src/handlebars.ts | 7 +-- packages/kbn-handlebars/src/visitor.ts | 42 ++++++------------ 4 files changed, 39 insertions(+), 60 deletions(-) diff --git a/packages/kbn-handlebars/index.test.ts b/packages/kbn-handlebars/index.test.ts index bdaebca946533..d95c6a1c8304a 100644 --- a/packages/kbn-handlebars/index.test.ts +++ b/packages/kbn-handlebars/index.test.ts @@ -506,12 +506,13 @@ describe('blocks', () => { it('should call multiple decorators in the same program body in the expected order and get the expected output', () => { let decoratorCall = 0; let progCall = 0; - expectTemplate('{{*decorator}}con{{*decorator}}tent') - .beforeRender(() => { + expectTemplate('{{*decorator}}con{{*decorator}}tent', { + beforeRender() { // ensure the counters are reset between EVAL/AST render calls decoratorCall = 0; progCall = 0; - }) + }, + }) .withInput({ decoratorCall: 0, progCall: 0, diff --git a/packages/kbn-handlebars/src/__jest__/test_bench.ts b/packages/kbn-handlebars/src/__jest__/test_bench.ts index 9bccae90a86ae..fa2626d11fbaf 100644 --- a/packages/kbn-handlebars/src/__jest__/test_bench.ts +++ b/packages/kbn-handlebars/src/__jest__/test_bench.ts @@ -24,6 +24,7 @@ global.kbnHandlebarsEnv = null; interface TestOptions { beforeEach?: Function; + beforeRender?: Function; } export function expectTemplate(template: string, options?: TestOptions) { @@ -39,7 +40,6 @@ export function forEachCompileFunctionName( class HandlebarsTestBench { private template: string; private options: TestOptions; - private beforeRenderFn: Function = () => {}; private compileOptions?: ExtendedCompileOptions; private runtimeOptions?: ExtendedRuntimeOptions; private helpers: { [name: string]: Handlebars.HelperDelegate | undefined } = {}; @@ -52,11 +52,6 @@ class HandlebarsTestBench { this.options = options; } - beforeRender(fn: Function) { - this.beforeRenderFn = fn; - return this; - } - withCompileOptions(compileOptions?: ExtendedCompileOptions) { this.compileOptions = compileOptions; return this; @@ -159,16 +154,14 @@ class HandlebarsTestBench { private compileAndExecuteEval() { const renderEval = this.compileEval(); - const runtimeOptions: ExtendedRuntimeOptions = Object.assign( - { - helpers: this.helpers, - partials: this.partials, - decorators: this.decorators, - }, - this.runtimeOptions - ); + const runtimeOptions: ExtendedRuntimeOptions = { + helpers: this.helpers as Record, + partials: this.partials as Record, + decorators: this.decorators, + ...this.runtimeOptions, + }; - this.beforeRenderFn(); + this.execBeforeRender(); return renderEval(this.input, runtimeOptions); } @@ -176,16 +169,14 @@ class HandlebarsTestBench { private compileAndExecuteAST() { const renderAST = this.compileAST(); - const runtimeOptions: ExtendedRuntimeOptions = Object.assign( - { - helpers: this.helpers, - partials: this.partials, - decorators: this.decorators, - }, - this.runtimeOptions - ); + const runtimeOptions: ExtendedRuntimeOptions = { + helpers: this.helpers as Record, + partials: this.partials as Record, + decorators: this.decorators, + ...this.runtimeOptions, + }; - this.beforeRenderFn(); + this.execBeforeRender(); return renderAST(this.input, runtimeOptions); } @@ -200,6 +191,10 @@ class HandlebarsTestBench { return handlebarsEnv.compileAST(this.template, this.compileOptions); } + private execBeforeRender() { + this.options.beforeRender?.(); + } + private execBeforeEach() { if (this.options.beforeEach) { this.options.beforeEach(); diff --git a/packages/kbn-handlebars/src/handlebars.ts b/packages/kbn-handlebars/src/handlebars.ts index d2cb1c258d679..91f6f33a6069e 100644 --- a/packages/kbn-handlebars/src/handlebars.ts +++ b/packages/kbn-handlebars/src/handlebars.ts @@ -7,7 +7,7 @@ // https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require import Handlebars from 'handlebars'; -import type { DecoratorsHash, ExtendedCompileOptions, ExtendedRuntimeOptions } from './types'; +import type { ExtendedCompileOptions, ExtendedRuntimeOptions } from './types'; import { ElasticHandlebarsVisitor } from './visitor'; const originalCreate = Handlebars.create; @@ -46,11 +46,8 @@ Handlebars.compileAST = function ( } // If `Handlebars.compileAST` is reassigned, `this` will be undefined. - const helpers = (this ?? Handlebars).helpers; - const partials = (this ?? Handlebars).partials; - const decorators = (this ?? Handlebars).decorators as DecoratorsHash; + const visitor = new ElasticHandlebarsVisitor(this ?? Handlebars, input, options); - const visitor = new ElasticHandlebarsVisitor(this, input, options, helpers, partials, decorators); return (context: any, runtimeOptions?: ExtendedRuntimeOptions) => visitor.render(context, runtimeOptions); }; diff --git a/packages/kbn-handlebars/src/visitor.ts b/packages/kbn-handlebars/src/visitor.ts index 397f896496329..c5962f4beb4db 100644 --- a/packages/kbn-handlebars/src/visitor.ts +++ b/packages/kbn-handlebars/src/visitor.ts @@ -27,7 +27,6 @@ import type { HelpersHash, NodeType, NonBlockHelperOptions, - PartialsHash, ProcessableBlockStatementNode, ProcessableNode, ProcessableNodeWithPathParts, @@ -51,9 +50,6 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { private template?: string; private compileOptions: ExtendedCompileOptions; private runtimeOptions?: ExtendedRuntimeOptions; - private initialHelpers: HelpersHash; - private initialPartials: PartialsHash; - private initialDecorators: DecoratorsHash; private blockParamNames: any[][] = []; private blockParamValues: any[][] = []; private ast?: hbs.AST.Program; @@ -65,10 +61,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { constructor( env: typeof Handlebars, input: string | hbs.AST.Program, - options: ExtendedCompileOptions = {}, - helpers: HelpersHash, - partials: PartialsHash, - decorators: DecoratorsHash + options: ExtendedCompileOptions = {} ) { super(); @@ -80,13 +73,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { this.template = input as string; } - this.compileOptions = Object.assign( - { - data: true, - }, - options - ); - + this.compileOptions = { data: true, ...options }; this.compileOptions.knownHelpers = Object.assign( Object.create(null), { @@ -102,10 +89,6 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { this.compileOptions.knownHelpers ); - this.initialHelpers = Object.assign({}, helpers); - this.initialPartials = Object.assign({}, partials); - this.initialDecorators = Object.assign({}, decorators); - const protoAccessControl = createProtoAccessControl({}); const container: Container = (this.container = { @@ -156,13 +139,16 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { render(context: any, options: ExtendedRuntimeOptions = {}): string { this.contexts = [context]; this.output = []; - this.runtimeOptions = Object.assign({}, options); - this.container.helpers = Object.assign(this.initialHelpers, options.helpers); - this.container.partials = Object.assign(this.initialPartials, options.partials); - this.container.decorators = Object.assign( - this.initialDecorators, - options.decorators as DecoratorsHash - ); + this.runtimeOptions = { ...options }; + this.container.helpers = { + ...this.env.helpers, + ...(options.helpers as HelpersHash), + }; + this.container.partials = { ...this.env.partials, ...options.partials }; + this.container.decorators = { + ...(this.env.decorators as DecoratorsHash), + ...(options.decorators as DecoratorsHash), + }; this.container.hooks = {}; this.processedRootDecorators = false; this.processedDecoratorsForProgram.clear(); @@ -540,7 +526,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { }; if (fn.partials) { - options.partials = Object.assign({}, options.partials, fn.partials); + options.partials = { ...options.partials, ...fn.partials }; } } @@ -694,7 +680,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { nextContext: any, runtimeOptions: ExtendedRuntimeOptions = {} ) => { - runtimeOptions = Object.assign({}, runtimeOptions); + runtimeOptions = { ...runtimeOptions }; // inherit data in blockParams from parent program runtimeOptions.data = runtimeOptions.data || this.runtimeOptions!.data; From 46abd89537a144f843b1eaed3082dbdc3071211f Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 9 Feb 2023 12:31:27 +0100 Subject: [PATCH 014/203] [Synthetics] Update scrolling e2e test (#150673) --- .../synthetics/overview_scrolling.journey.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts index dbbd9253d1d51..829223dabfe70 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts @@ -7,6 +7,7 @@ import { before, after, expect, journey, step } from '@elastic/synthetics'; import { recordVideo } from '@kbn/observability-plugin/e2e/record_video'; +import { RetryService } from '@kbn/ftr-common-functional-services'; import { addTestMonitor, cleanTestMonitors, @@ -14,10 +15,11 @@ import { } from './services/add_monitor'; import { syntheticsAppPageProvider } from '../../page_objects/synthetics/synthetics_app'; -journey('Overview Scrolling', async ({ page, params }) => { +journey('OverviewScrolling', async ({ page, params }) => { recordVideo(page); const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const retry: RetryService = params.getService('retry'); before(async () => { await enableMonitorManagedViaApi(params.kibanaUrl); @@ -47,20 +49,18 @@ journey('Overview Scrolling', async ({ page, params }) => { }); step('scroll until you see showing all monitors', async () => { - let showingAllMonitorsNode; - const gridItems = await page.locator(`[data-test-subj="syntheticsOverviewGridItem"]`); await page.waitForSelector(`text="test monitor 0"`); let count = await gridItems.count(); expect(count <= 32).toBe(true); - while (!showingAllMonitorsNode) { + await retry.tryForTime(90 * 1000, async () => { await page.mouse.wheel(0, 100); - showingAllMonitorsNode = await page.$(`text="Showing all monitors"`); - } - - expect(await showingAllMonitorsNode.isVisible()).toBe(true); + const showingAllMonitorsNode = await page.$(`text="Showing all monitors"`); + expect(showingAllMonitorsNode).toBeTruthy(); + expect(await showingAllMonitorsNode?.isVisible()).toBe(true); + }); count = await gridItems.count(); expect(count).toBe(100); From 9fac2c4e818aca8ffc8c3fff0f66fb821c724540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Thu, 9 Feb 2023 12:37:00 +0100 Subject: [PATCH 015/203] fix failing test (#150589) Fixes https://github.com/elastic/kibana/issues/150565 Fixes https://github.com/elastic/kibana/issues/150566 --- .../api_integration/apis/uptime/rest/index.ts | 2 +- ...n.ts => uptime_integration_deprecation.ts} | 39 ++++--------------- 2 files changed, 9 insertions(+), 32 deletions(-) rename x-pack/test/api_integration/apis/uptime/rest/{uptime_zip_url_deprecation.ts => uptime_integration_deprecation.ts} (77%) diff --git a/x-pack/test/api_integration/apis/uptime/rest/index.ts b/x-pack/test/api_integration/apis/uptime/rest/index.ts index e83283b730c73..738669a330d5a 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/index.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/index.ts @@ -70,7 +70,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./monitor_duration')); loadTestFile(require.resolve('./index_status')); loadTestFile(require.resolve('./monitor_states_real_data')); - loadTestFile(require.resolve('./uptime_zip_url_deprecation.ts')); + loadTestFile(require.resolve('./uptime_integration_deprecation.ts')); }); }); } diff --git a/x-pack/test/api_integration/apis/uptime/rest/uptime_zip_url_deprecation.ts b/x-pack/test/api_integration/apis/uptime/rest/uptime_integration_deprecation.ts similarity index 77% rename from x-pack/test/api_integration/apis/uptime/rest/uptime_zip_url_deprecation.ts rename to x-pack/test/api_integration/apis/uptime/rest/uptime_integration_deprecation.ts index a2fda06d05ae9..6d9b0497ac09c 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/uptime_zip_url_deprecation.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/uptime_integration_deprecation.ts @@ -65,9 +65,7 @@ export default function (providerContext: FtrProviderContext) { ], }); - // Failing: See https://github.com/elastic/kibana/issues/150565 - // Failing: See https://github.com/elastic/kibana/issues/150566 - describe.skip('UptimeZipUrlDeprecation', () => { + describe('UptimeIntegrationDeprecation', () => { let agentPolicyId: string; before(async function () { @@ -80,25 +78,6 @@ export default function (providerContext: FtrProviderContext) { }) .expect(200); agentPolicyId = agentPolicyResponse.item.id; - - // create a policy without a zip url - await supertest - .post(`/api/fleet/package_policies`) - .set('kbn-xsrf', 'xxxx') - .send({ - name: `synthetics-test ${uuidv4()}`, - description: '', - namespace: 'default', - policy_id: agentPolicyId, - enabled: true, - inputs: [getBrowserZipInput()], - package: { - name: 'synthetics', - title: 'For Synthetics Tests', - version: '0.10.2', - }, - }) - .expect(200); }); after(async function () { @@ -108,17 +87,17 @@ export default function (providerContext: FtrProviderContext) { .send({ agentPolicyId }); }); - it('should return hasZipUrlMonitors false when there are not any zip url policies', async function () { + it('should return hasIntegrationMonitors false when there are not any zip url policies', async function () { const { body } = await supertest - .get(`/internal/uptime/fleet/has_zip_url_monitors`) + .get(`/internal/uptime/fleet/has_integration_monitors`) .set('kbn-xsrf', 'xxxx') .send() .expect(200); - expect(body.hasZipUrlMonitors).to.eql(false); + expect(body.hasIntegrationMonitors).to.eql(false); }); - it('should return hasZipUrlMonitors true when there are zip url policies', async function () { + it('should return hasIntegrationMonitors true when there are zip url policies', async function () { const { body } = await supertest .post(`/api/fleet/package_policies`) .set('kbn-xsrf', 'xxxx') @@ -128,7 +107,7 @@ export default function (providerContext: FtrProviderContext) { namespace: 'default', policy_id: agentPolicyId, enabled: true, - inputs: [getBrowserZipInput('testZipUrl')], + inputs: [getBrowserZipInput()], package: { name: 'synthetics', title: 'For Synthetics Tests', @@ -139,15 +118,13 @@ export default function (providerContext: FtrProviderContext) { const policyId = body.item.id; - expect(body.item.inputs[0].streams[0].vars['source.zip_url.url'].value).to.eql('testZipUrl'); - const { body: response } = await supertest - .get(`/internal/uptime/fleet/has_zip_url_monitors`) + .get(`/internal/uptime/fleet/has_integration_monitors`) .set('kbn-xsrf', 'xxxx') .send() .expect(200); - expect(response.hasZipUrlMonitors).to.eql(true); + expect(response.hasIntegrationMonitors).to.eql(true); // delete policy we just made await supertest From d341cc3157a2ad942d543a5ba0d7e6f7665d26e2 Mon Sep 17 00:00:00 2001 From: Yan Savitski Date: Thu, 9 Feb 2023 13:03:26 +0100 Subject: [PATCH 016/203] =?UTF-8?q?[Behavioral=20Analytics]=20add=20behavi?= =?UTF-8?q?oural=20analytics=20to=20doc=5Flinks=20+=20updat=E2=80=A6=20(#1?= =?UTF-8?q?50617)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixing issue https://github.com/elastic/enterprise-search-team/issues/3899 Added url to behavioral analytics and updated link --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + packages/kbn-doc-links/src/types.ts | 1 + .../analytics_collection_view/analytics_collection_events.tsx | 3 ++- .../public/applications/shared/doc_links/doc_links.ts | 3 +++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 5903bd136ed1f..845e5be7d8b7b 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -124,6 +124,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { }, enterpriseSearch: { apiKeys: `${KIBANA_DOCS}api-keys.html`, + behavioralAnalytics: `${ENTERPRISE_SEARCH_DOCS}analytics-overview.html`, behavioralAnalyticsEvents: `${ENTERPRISE_SEARCH_DOCS}analytics-events.html`, bulkApi: `${ELASTICSEARCH_DOCS}docs-bulk.html`, configuration: `${ENTERPRISE_SEARCH_DOCS}configuration.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index f7b4019eb599a..6d2cc1e119594 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -109,6 +109,7 @@ export interface DocLinks { }; readonly enterpriseSearch: { readonly apiKeys: string; + readonly behavioralAnalytics: string; readonly behavioralAnalyticsEvents: string; readonly bulkApi: string; readonly configuration: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_events.tsx b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_events.tsx index d847f50f3ca3d..e690605a7b5b5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_events.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_events.tsx @@ -15,6 +15,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { ENTERPRISE_SEARCH_ANALYTICS_LOGS_SOURCE_ID } from '../../../../../common/constants'; import { AnalyticsCollection } from '../../../../../common/types/analytics'; +import { docLinks } from '../../../shared/doc_links'; import { generateEncodedPath } from '../../../shared/encode_path_params'; import { KibanaLogic } from '../../../shared/kibana'; @@ -97,7 +98,7 @@ export const AnalyticsCollectionEvents: React.FC } footer={ - + {i18n.translate( 'xpack.enterpriseSearch.analytics.collections.collectionsView.eventsTab.emptyState.footer', { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts index 073ffe6abca3f..e2dcccec2adeb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts @@ -34,6 +34,7 @@ class DocLinks { public appSearchWebCrawler: string; public appSearchWebCrawlerEventLogs: string; public appSearchWebCrawlerReference: string; + public behavioralAnalytics: string; public behavioralAnalyticsEvents: string; public bulkApi: string; public clientsGoIndex: string; @@ -150,6 +151,7 @@ class DocLinks { this.appSearchWebCrawler = ''; this.appSearchWebCrawlerEventLogs = ''; this.appSearchWebCrawlerReference = ''; + this.behavioralAnalytics = ''; this.behavioralAnalyticsEvents = ''; this.bulkApi = ''; this.clientsGoIndex = ''; @@ -268,6 +270,7 @@ class DocLinks { this.appSearchWebCrawler = docLinks.links.appSearch.webCrawler; this.appSearchWebCrawlerEventLogs = docLinks.links.appSearch.webCrawlerEventLogs; this.appSearchWebCrawlerReference = docLinks.links.appSearch.webCrawlerReference; + this.behavioralAnalytics = docLinks.links.enterpriseSearch.behavioralAnalytics; this.behavioralAnalyticsEvents = docLinks.links.enterpriseSearch.behavioralAnalyticsEvents; this.bulkApi = docLinks.links.enterpriseSearch.bulkApi; this.clientsGoIndex = docLinks.links.clients.goIndex; From 050343b6abd487a83a943e7e14be5ae5d075d564 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Thu, 9 Feb 2023 13:43:52 +0100 Subject: [PATCH 017/203] [Fleet] Disable Request Diagnostics for agents < 8.7 and added API validation (#150555) ## Summary Fixes https://github.com/elastic/kibana/issues/150300 Disable button on single agent Request Diagnostics action if agent does not support it (<8.7 version). Added a tooltip as well on Diagnostics tab button. Added validation to single and bulk API to reject actions where agent is older. image image When bulk actioning with one new and one old version, one of the agents will fail (visible in Agent activity) image ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kyle Pollich Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/fleet/common/services/index.ts | 4 + ...gent_request_diagnostics_supported.test.ts | 42 ++++++++++ .../is_agent_request_diagnostics_supported.ts | 20 +++++ .../components/actions_menu.tsx | 4 +- .../components/agent_diagnostics/index.tsx | 40 ++++++++-- .../components/table_row_actions.tsx | 4 +- .../agent/request_diagnostics_handler.test.ts | 78 +++++++++++++++++++ .../agent/request_diagnostics_handler.ts | 15 ++++ .../server/services/agents/action.mock.ts | 44 ++++++++++- .../agents/request_diagnostics.test.ts | 36 ++++++++- .../request_diagnostics_action_runner.ts | 22 +++++- .../es_archives/fleet/agents/data.json | 6 +- 12 files changed, 299 insertions(+), 16 deletions(-) create mode 100644 x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.test.ts create mode 100644 x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.ts create mode 100644 x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.test.ts diff --git a/x-pack/plugins/fleet/common/services/index.ts b/x-pack/plugins/fleet/common/services/index.ts index 2b5a8dd04bc91..2b700a6aaca6f 100644 --- a/x-pack/plugins/fleet/common/services/index.ts +++ b/x-pack/plugins/fleet/common/services/index.ts @@ -20,6 +20,10 @@ export { isValidNamespace, INVALID_NAMESPACE_CHARACTERS } from './is_valid_names export { isDiffPathProtocol } from './is_diff_path_protocol'; export { LicenseService } from './license'; export { isAgentUpgradeable } from './is_agent_upgradeable'; +export { + isAgentRequestDiagnosticsSupported, + MINIMUM_DIAGNOSTICS_AGENT_VERSION, +} from './is_agent_request_diagnostics_supported'; export { isInputOnlyPolicyTemplate, isIntegrationPolicyTemplate, diff --git a/x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.test.ts b/x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.test.ts new file mode 100644 index 0000000000000..cfe64a82ff5d7 --- /dev/null +++ b/x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.test.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 type { Agent } from '../types/models/agent'; + +import { isAgentRequestDiagnosticsSupported } from '.'; + +const getAgent = ({ version }: { version: string }): Agent => { + const agent: Agent = { + id: 'agent1', + active: true, + type: 'PERMANENT', + enrolled_at: '2023-02-08T20:24:08.347Z', + user_provided_metadata: {}, + local_metadata: { + elastic: { + agent: { + version, + }, + }, + }, + packages: ['system'], + }; + return agent; +}; +describe('Fleet - isAgentRequestDiagnosticsSupported', () => { + it('returns false if agent version < 8.7', () => { + expect(isAgentRequestDiagnosticsSupported(getAgent({ version: '7.9.0' }))).toBe(false); + }); + + it('returns true if agent version is 8.7', () => { + expect(isAgentRequestDiagnosticsSupported(getAgent({ version: '8.7.0' }))).toBe(true); + }); + + it('returns true if agent version > 8.7', () => { + expect(isAgentRequestDiagnosticsSupported(getAgent({ version: '8.8.0' }))).toBe(true); + }); +}); diff --git a/x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.ts b/x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.ts new file mode 100644 index 0000000000000..c912120e6b473 --- /dev/null +++ b/x-pack/plugins/fleet/common/services/is_agent_request_diagnostics_supported.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 semverGte from 'semver/functions/gte'; + +import type { Agent } from '../types'; + +export const MINIMUM_DIAGNOSTICS_AGENT_VERSION = '8.7.0'; + +export function isAgentRequestDiagnosticsSupported(agent: Agent) { + if (typeof agent?.local_metadata?.elastic?.agent?.version !== 'string') { + return false; + } + const agentVersion = agent.local_metadata.elastic.agent.version; + return semverGte(agentVersion, MINIMUM_DIAGNOSTICS_AGENT_VERSION); +} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/actions_menu.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/actions_menu.tsx index 76bcd21c0207c..2a3d29226371c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/actions_menu.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/actions_menu.tsx @@ -9,6 +9,8 @@ import React, { memo, useState, useMemo } from 'react'; import { EuiPortal, EuiContextMenuItem } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { isAgentRequestDiagnosticsSupported } from '../../../../../../../common/services'; + import type { Agent, AgentPolicy } from '../../../../types'; import { useAuthz, useKibanaVersion } from '../../../../hooks'; import { ContextMenuActions } from '../../../../components'; @@ -99,7 +101,7 @@ export const AgentDetailsActionMenu: React.FunctionComponent<{ menuItems.push( { setIsRequestDiagnosticsModalOpen(true); }} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_diagnostics/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_diagnostics/index.tsx index 2c38fdfba536b..180a1b894ca13 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_diagnostics/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_diagnostics/index.tsx @@ -25,6 +25,11 @@ import styled from 'styled-components'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import { + isAgentRequestDiagnosticsSupported, + MINIMUM_DIAGNOSTICS_AGENT_VERSION, +} from '../../../../../../../../common/services'; + import { sendGetAgentUploads, sendPostRequestDiagnostics, @@ -215,6 +220,20 @@ export const AgentDiagnosticsTab: React.FunctionComponent } } + const requestDiagnosticsButton = ( + + + + ); + return ( @@ -235,12 +254,21 @@ export const AgentDiagnosticsTab: React.FunctionComponent - - - + {isAgentRequestDiagnosticsSupported(agent) ? ( + requestDiagnosticsButton + ) : ( + + } + > + {requestDiagnosticsButton} + + )} {isLoading ? ( diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_row_actions.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_row_actions.tsx index 6fdf4016d457f..243eabadcf3b7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_row_actions.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_list_page/components/table_row_actions.tsx @@ -9,6 +9,8 @@ import React, { useState } from 'react'; import { EuiContextMenuItem } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; +import { isAgentRequestDiagnosticsSupported } from '../../../../../../../common/services'; + import type { Agent, AgentPolicy } from '../../../../types'; import { useAuthz, useLink, useKibanaVersion } from '../../../../hooks'; import { ContextMenuActions } from '../../../../components'; @@ -114,7 +116,7 @@ export const TableRowActions: React.FunctionComponent<{ menuItems.push( { onRequestDiagnosticsClick(); }} diff --git a/x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.test.ts b/x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.test.ts new file mode 100644 index 0000000000000..e47b056544ee4 --- /dev/null +++ b/x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.test.ts @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { + ElasticsearchClient, + KibanaResponseFactory, + RequestHandlerContext, + SavedObjectsClientContract, + KibanaRequest, +} from '@kbn/core/server'; +import { + elasticsearchServiceMock, + savedObjectsClientMock, + httpServerMock, +} from '@kbn/core/server/mocks'; + +import { getAgentById } from '../../services/agents'; +import * as AgentService from '../../services/agents'; + +import { requestDiagnosticsHandler } from './request_diagnostics_handler'; + +jest.mock('../../services/agents'); + +const mockGetAgentById = getAgentById as jest.Mock; + +describe('request diagnostics handler', () => { + let mockResponse: jest.Mocked; + let mockSavedObjectsClient: jest.Mocked; + let mockElasticsearchClient: jest.Mocked; + let mockContext: RequestHandlerContext; + let mockRequest: KibanaRequest<{ agentId: string }, undefined, undefined, any>; + + beforeEach(() => { + mockSavedObjectsClient = savedObjectsClientMock.create(); + mockElasticsearchClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + mockResponse = httpServerMock.createResponseFactory(); + jest.spyOn(AgentService, 'requestDiagnostics').mockResolvedValue({ actionId: '1' }); + mockContext = { + core: { + savedObjects: { + client: mockSavedObjectsClient, + }, + elasticsearch: { + client: { + asInternalUser: mockElasticsearchClient, + }, + }, + }, + } as unknown as RequestHandlerContext; + mockRequest = httpServerMock.createKibanaRequest({ params: { agentId: 'agent1' } }); + }); + + it('should return ok if agent supports request diagnostics', async () => { + mockGetAgentById.mockResolvedValueOnce({ + local_metadata: { elastic: { agent: { version: '8.7.0' } } }, + }); + + await requestDiagnosticsHandler(mockContext, mockRequest, mockResponse); + + expect(mockResponse.ok).toHaveBeenCalledWith({ body: { actionId: '1' } }); + }); + + it('should retur error if agent does not support request diagnostics', async () => { + mockGetAgentById.mockResolvedValueOnce({ + local_metadata: { elastic: { agent: { version: '8.6.0' } } }, + }); + + await requestDiagnosticsHandler(mockContext, mockRequest, mockResponse); + + expect(mockResponse.customError).toHaveBeenCalledWith({ + body: { message: 'Agent agent1 does not support request diagnostics action.' }, + statusCode: 400, + }); + }); +}); diff --git a/x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.ts b/x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.ts index 74452b0e055c7..d4598101580ef 100644 --- a/x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.ts +++ b/x-pack/plugins/fleet/server/routes/agent/request_diagnostics_handler.ts @@ -8,12 +8,15 @@ import type { RequestHandler } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; +import { isAgentRequestDiagnosticsSupported } from '../../../common/services'; + import * as AgentService from '../../services/agents'; import type { PostBulkRequestDiagnosticsActionRequestSchema, PostRequestDiagnosticsActionRequestSchema, } from '../../types'; import { defaultFleetErrorHandler } from '../../errors'; +import { getAgentById } from '../../services/agents'; export const requestDiagnosticsHandler: RequestHandler< TypeOf, @@ -22,7 +25,19 @@ export const requestDiagnosticsHandler: RequestHandler< > = async (context, request, response) => { const coreContext = await context.core; const esClient = coreContext.elasticsearch.client.asInternalUser; + const soClient = coreContext.savedObjects.client; try { + const agent = await getAgentById(esClient, soClient, request.params.agentId); + + if (!isAgentRequestDiagnosticsSupported(agent)) { + return response.customError({ + statusCode: 400, + body: { + message: `Agent ${request.params.agentId} does not support request diagnostics action.`, + }, + }); + } + const result = await AgentService.requestDiagnostics(esClient, request.params.agentId); return response.ok({ body: { actionId: result.actionId } }); diff --git a/x-pack/plugins/fleet/server/services/agents/action.mock.ts b/x-pack/plugins/fleet/server/services/agents/action.mock.ts index 3534327e196db..a0aa70d1491ff 100644 --- a/x-pack/plugins/fleet/server/services/agents/action.mock.ts +++ b/x-pack/plugins/fleet/server/services/agents/action.mock.ts @@ -56,6 +56,28 @@ export function createClientMock() { status: ['online'], }, }; + const agentInRegularDocNewer = { + _id: 'agent-in-regular-policy-newer', + _index: 'index', + _source: { + policy_id: 'regular-agent-policy', + local_metadata: { elastic: { agent: { version: '8.7.0', upgradeable: true } } }, + }, + fields: { + status: ['online'], + }, + }; + const agentInRegularDocNewer2 = { + _id: 'agent-in-regular-policy-newer2', + _index: 'index', + _source: { + policy_id: 'regular-agent-policy', + local_metadata: { elastic: { agent: { version: '8.7.0', upgradeable: true } } }, + }, + fields: { + status: ['online'], + }, + }; const regularAgentPolicySO = { id: 'regular-agent-policy', attributes: { is_managed: false }, @@ -109,6 +131,10 @@ export function createClientMock() { return { body: agentInRegularDoc2 }; case agentInRegularDoc._id: return { body: agentInRegularDoc }; + case agentInRegularDocNewer._id: + return { body: agentInRegularDocNewer }; + case agentInRegularDocNewer2._id: + return { body: agentInRegularDocNewer2 }; default: throw new Error('not found'); } @@ -135,6 +161,12 @@ export function createClientMock() { case agentInRegularDoc._id: result = agentInRegularDoc; break; + case agentInRegularDocNewer._id: + result = agentInRegularDocNewer; + break; + case agentInRegularDocNewer2._id: + result = agentInRegularDocNewer2; + break; default: throw new Error('not found'); } @@ -157,9 +189,15 @@ export function createClientMock() { total: 1, }, hits: { - hits: [agentInHostedDoc, agentInRegularDoc, agentInRegularDoc2], + hits: [ + agentInHostedDoc, + agentInRegularDoc, + agentInRegularDoc2, + agentInRegularDocNewer, + agentInRegularDocNewer2, + ], total: { - value: 3, + value: 5, relation: 'eq', }, }, @@ -173,6 +211,8 @@ export function createClientMock() { agentInHostedDoc2, agentInRegularDoc, agentInRegularDoc2, + agentInRegularDocNewer, + agentInRegularDocNewer2, regularAgentPolicySO, hostedAgentPolicySO, regularAgentPolicySO2, diff --git a/x-pack/plugins/fleet/server/services/agents/request_diagnostics.test.ts b/x-pack/plugins/fleet/server/services/agents/request_diagnostics.test.ts index 05aa81be27612..3c459ce178a3a 100644 --- a/x-pack/plugins/fleet/server/services/agents/request_diagnostics.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/request_diagnostics.test.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { appContextService } from '../app_context'; import { createAppContextStartContractMock } from '../../mocks'; @@ -37,18 +38,45 @@ describe('requestDiagnostics (plural)', () => { appContextService.stop(); }); it('can request diagnostics for multiple agents', async () => { - const { soClient, esClient, agentInRegularDoc, agentInRegularDoc2 } = createClientMock(); - const idsToUnenroll = [agentInRegularDoc._id, agentInRegularDoc2._id]; - await bulkRequestDiagnostics(esClient, soClient, { agentIds: idsToUnenroll }); + const { soClient, esClient, agentInRegularDocNewer, agentInRegularDocNewer2 } = + createClientMock(); + const idsToAction = [agentInRegularDocNewer._id, agentInRegularDocNewer2._id]; + await bulkRequestDiagnostics(esClient, soClient, { agentIds: idsToAction }); expect(esClient.create).toHaveBeenCalledWith( expect.objectContaining({ body: expect.objectContaining({ - agents: ['agent-in-regular-policy', 'agent-in-regular-policy2'], + agents: ['agent-in-regular-policy-newer', 'agent-in-regular-policy-newer2'], type: 'REQUEST_DIAGNOSTICS', }), index: '.fleet-actions', }) ); }); + + it('should report error when diagnostics for older agent', async () => { + const { soClient, esClient, agentInRegularDoc, agentInRegularDocNewer } = createClientMock(); + const idsToAction = [agentInRegularDocNewer._id, agentInRegularDoc._id]; + await bulkRequestDiagnostics(esClient, soClient, { agentIds: idsToAction }); + + expect(esClient.create).toHaveBeenCalledWith( + expect.objectContaining({ + body: expect.objectContaining({ + agents: ['agent-in-regular-policy-newer', 'agent-in-regular-policy'], + type: 'REQUEST_DIAGNOSTICS', + }), + index: '.fleet-actions', + }) + ); + const calledWithActionResults = esClient.bulk.mock.calls[0][0] as estypes.BulkRequest; + // bulk write two line per create + expect(calledWithActionResults.body?.length).toBe(2); + const expectedObject = expect.objectContaining({ + '@timestamp': expect.anything(), + action_id: expect.anything(), + agent_id: 'agent-in-regular-policy', + error: 'Agent agent-in-regular-policy does not support request diagnostics action.', + }); + expect(calledWithActionResults.body?.[1] as any).toEqual(expectedObject); + }); }); diff --git a/x-pack/plugins/fleet/server/services/agents/request_diagnostics_action_runner.ts b/x-pack/plugins/fleet/server/services/agents/request_diagnostics_action_runner.ts index d9552f3a1a41e..88cb2d5770688 100644 --- a/x-pack/plugins/fleet/server/services/agents/request_diagnostics_action_runner.ts +++ b/x-pack/plugins/fleet/server/services/agents/request_diagnostics_action_runner.ts @@ -8,10 +8,14 @@ import { v4 as uuidv4 } from 'uuid'; import type { ElasticsearchClient } from '@kbn/core/server'; +import { isAgentRequestDiagnosticsSupported } from '../../../common/services'; + import type { Agent } from '../../types'; +import { FleetError } from '../../errors'; + import { ActionRunner } from './action_runner'; -import { createAgentAction } from './actions'; +import { createAgentAction, createErrorActionResults } from './actions'; import { BulkActionTaskType } from './bulk_action_types'; export class RequestDiagnosticsActionRunner extends ActionRunner { @@ -36,11 +40,20 @@ export async function requestDiagnosticsBatch( total?: number; } ): Promise<{ actionId: string }> { + const errors: Record = {}; const now = new Date().toISOString(); const actionId = options.actionId ?? uuidv4(); const total = options.total ?? givenAgents.length; + givenAgents.forEach((agent: Agent) => { + if (!isAgentRequestDiagnosticsSupported(agent)) { + errors[agent.id] = new FleetError( + `Agent ${agent.id} does not support request diagnostics action.` + ); + } + }); + const agentIds = givenAgents.map((agent) => agent.id); await createAgentAction(esClient, { @@ -51,6 +64,13 @@ export async function requestDiagnosticsBatch( total, }); + await createErrorActionResults( + esClient, + actionId, + errors, + 'agent does not support request diagnostics action' + ); + return { actionId, }; diff --git a/x-pack/test/functional/es_archives/fleet/agents/data.json b/x-pack/test/functional/es_archives/fleet/agents/data.json index 14f3704cdb623..257dbb2003f69 100644 --- a/x-pack/test/functional/es_archives/fleet/agents/data.json +++ b/x-pack/test/functional/es_archives/fleet/agents/data.json @@ -8,7 +8,11 @@ "active": true, "policy_id": "policy1", "type": "PERMANENT", - "local_metadata": { "host": {"hostname": "host1"}}, + "local_metadata": { "host": {"hostname": "host1"}, "elastic": { + "agent": { + "version": "8.7.0" + } + }}, "user_provided_metadata": {}, "enrolled_at": "2022-06-21T12:14:25Z", "last_checkin": "2022-06-27T12:26:29Z", From d1ef916c4f407d4c31ff5e37687294b49fd6a929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Zolt=C3=A1n=20Szab=C3=B3?= Date: Thu, 9 Feb 2023 13:57:37 +0100 Subject: [PATCH 018/203] [ML] Adjusts anomaly detection screenshot script (#150584) ## Summary This PR makes adjustments on one of the anomaly detection screenshot scripts: * renames the test file to `influencers` from `population_analysis`, * renames one of the screenshots in the script, * removes two screenshot creation steps. The reason behind all of this is that the doc page about population analysis has been replaced by another, higher-level page that doesn't contain any screenshots. Two screenshots covered in this test file became unnecessary because of this. The third one, however, captures every information required for another screenshot in the docs about influencers. --- .../apps/ml_docs/anomaly_detection/index.ts | 2 +- ...{population_analysis.ts => influencers.ts} | 42 +------------------ 2 files changed, 2 insertions(+), 42 deletions(-) rename x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/{population_analysis.ts => influencers.ts} (57%) diff --git a/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/index.ts b/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/index.ts index 3d83fd1cfde70..697c115cee2ad 100644 --- a/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/index.ts +++ b/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/index.ts @@ -11,7 +11,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('anomaly detection', function () { loadTestFile(require.resolve('./geographic_data')); loadTestFile(require.resolve('./generate_anomaly_alerts')); - loadTestFile(require.resolve('./population_analysis')); + loadTestFile(require.resolve('./influencers')); loadTestFile(require.resolve('./custom_urls')); loadTestFile(require.resolve('./mapping_anomalies')); loadTestFile(require.resolve('./finding_anomalies')); diff --git a/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/population_analysis.ts b/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/influencers.ts similarity index 57% rename from x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/population_analysis.ts rename to x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/influencers.ts index caad3cc76ae5c..03154b7d8511b 100644 --- a/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/population_analysis.ts +++ b/x-pack/test/screenshot_creation/apps/ml_docs/anomaly_detection/influencers.ts @@ -41,9 +41,6 @@ export default function ({ getService }: FtrProviderContext) { query: { bool: { must: [{ match_all: {} }] } }, }; - const cellSize = 15; - const viewBySwimLaneTestSubj = 'mlAnomalyExplorerSwimlaneViewBy'; - describe('population analysis', function () { before(async () => { await ml.api.createAndRunAnomalyDetectionLookbackJob( @@ -58,22 +55,6 @@ export default function ({ getService }: FtrProviderContext) { await ml.api.cleanMlIndices(); }); - it('wizard screenshot', async () => { - await ml.testExecution.logTestStep('navigate to job list'); - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.testExecution.logTestStep('open job in wizard'); - await ml.jobTable.filterWithSearchString(populationJobConfig.job_id, 1); - await ml.jobTable.clickCloneJobAction(populationJobConfig.job_id); - await ml.jobTypeSelection.assertPopulationJobWizardOpen(); - - await ml.testExecution.logTestStep('continue to the pick fields step and take screenshot'); - await ml.jobWizardCommon.advanceToPickFieldsSection(); - await commonScreenshots.removeFocusFromElement(); - await commonScreenshots.takeScreenshot('ml-population-job', screenshotDirectories); - }); - it('anomaly explorer screenshots', async () => { await ml.testExecution.logTestStep('navigate to job list'); await ml.navigation.navigateToMl(); @@ -84,28 +65,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.jobTable.filterWithSearchString(populationJobConfig.job_id, 1); await ml.jobTable.clickOpenJobInAnomalyExplorerButton(populationJobConfig.job_id); await ml.commonUI.waitForMlLoadingIndicatorToDisappear(); - await commonScreenshots.takeScreenshot('ml-population-results', screenshotDirectories); - await ml.testExecution.logTestStep( - 'select swim lane tile, expand anomaly row and take screenshot' - ); - const cells = await ml.swimLane.getCells(viewBySwimLaneTestSubj); - const sampleCell = cells[0]; - await ml.swimLane.selectSingleCell(viewBySwimLaneTestSubj, { - x: sampleCell.x + cellSize, - y: sampleCell.y + cellSize, - }); - await ml.swimLane.waitForSwimLanesToLoad(); - - await ml.anomalyExplorer.scrollChartsContainerIntoView(); - await ml.anomaliesTable.ensureDetailsOpen(0); - await ml.anomaliesTable.scrollRowIntoView(0); - await ml.testExecution.logTestStep('take screenshot'); - await commonScreenshots.takeScreenshot( - 'ml-population-anomaly', - screenshotDirectories, - 1500, - 1300 - ); + await commonScreenshots.takeScreenshot('influencers', screenshotDirectories); }); }); } From 90590d0ac5131e4f39ad625d5f7ca8dec09478c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Thu, 9 Feb 2023 14:03:12 +0100 Subject: [PATCH 019/203] [@kbn/plugin-generator] Skip `.i18nrc.json` for internal plugins (#150556) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/integration_tests/generate_plugin.test.ts | 1 - packages/kbn-plugin-generator/src/render_template.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts b/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts index ce359d1eb8104..6f48e872d74be 100644 --- a/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts +++ b/packages/kbn-plugin-generator/src/integration_tests/generate_plugin.test.ts @@ -83,7 +83,6 @@ it('generates a plugin without UI', async () => { Array [ /plugins/bar/.eslintrc.js, /plugins/bar/.gitignore, - /plugins/bar/.i18nrc.json, /plugins/bar/common/index.ts, /plugins/bar/kibana.json, /plugins/bar/package.json, diff --git a/packages/kbn-plugin-generator/src/render_template.ts b/packages/kbn-plugin-generator/src/render_template.ts index f64796ecad3dd..f2cb8c18a88d4 100644 --- a/packages/kbn-plugin-generator/src/render_template.ts +++ b/packages/kbn-plugin-generator/src/render_template.ts @@ -86,7 +86,7 @@ export async function renderTemplates({ excludeFiles( ([] as string[]).concat( answers.ui ? [] : 'public/**/*', - answers.ui && !answers.internal ? [] : ['translations/**/*', 'i18nrc.json'], + answers.ui && !answers.internal ? [] : ['translations/**/*', '.i18nrc.json'], answers.server ? [] : 'server/**/*', !answers.internal ? [] : ['.eslintrc.js', 'tsconfig.json', 'package.json', '.gitignore'] ) From 95401092deab4a6dc2d576593856ab3ac044db26 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 9 Feb 2023 13:07:24 +0000 Subject: [PATCH 020/203] skip flaky suite (#150343) --- x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts index 7e8a6c4f441a2..c599556a445a3 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts @@ -23,6 +23,7 @@ export default function (providerContext: FtrProviderContext) { }; // Failing: See https://github.com/elastic/kibana/issues/149844 + // FLAKY: https://github.com/elastic/kibana/issues/150343 describe.skip('installs package that has a prerelease version', async () => { skipIfNoDockerRegistry(providerContext); setupFleetAndAgents(providerContext); From ecc23e769056332a07b0b7b1e5440008291ca3f4 Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 9 Feb 2023 08:13:10 -0500 Subject: [PATCH 021/203] Upgrade transitive dependency http-cache-semantics (#150231) ## Summary Specify version 4.1.1 or greater for `http-cache-semantics` --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5a76dd4b92000..8485c0376b5e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17278,9 +17278,9 @@ htmlparser2@~3.3.0: readable-stream "1.0" http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" - integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + version "4.1.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" + integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== http-deceiver@^1.2.7: version "1.2.7" From d2fb7a51b2422d3f1ed11f1a6cbe4fa471893081 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Thu, 9 Feb 2023 08:27:20 -0500 Subject: [PATCH 022/203] [Fleet] Fix action creation for FORCE_UNENROLL (#150632) --- .../fleet/server/services/agents/unenroll_action_runner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 8f9a7f3763cc0..8aae49b754ef7 100644 --- a/x-pack/plugins/fleet/server/services/agents/unenroll_action_runner.ts +++ b/x-pack/plugins/fleet/server/services/agents/unenroll_action_runner.ts @@ -137,7 +137,7 @@ export async function updateActionsForForceUnenroll( // creating an action doc so that force unenroll shows up in activity await createAgentAction(esClient, { id: actionId, - agents: [], + agents: agentIds, created_at: new Date().toISOString(), type: 'FORCE_UNENROLL', total, From 265e4857df874ecbcd67f4d2ca0cc835d0545aa1 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 9 Feb 2023 14:43:34 +0100 Subject: [PATCH 023/203] [Synthetics] Fix errors duration formatting (#150613) --- .../hooks/use_failed_tests_by_step.tsx | 21 ++++++++++++---- .../hooks/use_monitor_errors.tsx | 15 +++++++++--- .../monitor_details_location.tsx | 24 +++++++++++++++---- .../monitor_errors/errors_list.tsx | 4 ++-- .../monitor_errors/failed_tests_count.tsx | 6 ++++- 5 files changed, 55 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_failed_tests_by_step.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_failed_tests_by_step.tsx index 5997d7969bc9f..f6688c0f8c1dc 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_failed_tests_by_step.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_failed_tests_by_step.tsx @@ -5,9 +5,10 @@ * 2.0. */ -import { useEsSearch } from '@kbn/observability-plugin/public'; import { useParams } from 'react-router-dom'; import { useMemo } from 'react'; +import { useReduxEsSearch } from '../../../hooks/use_redux_es_search'; +import { useSelectedLocation } from './use_selected_location'; import { createEsQuery } from '../../../../../../common/utils/es_search'; import { Ping } from '../../../../../../common/runtime_types'; import { STEP_END_FILTER } from '../../../../../../common/constants/data_filters'; @@ -19,6 +20,8 @@ export function useFailedTestByStep({ to, from }: { to: string; from: string }) const { monitorId } = useParams<{ monitorId: string }>(); + const selectedLocation = useSelectedLocation(); + const params = createEsQuery({ index: SYNTHETICS_INDEX_PATTERN, body: { @@ -41,6 +44,11 @@ export function useFailedTestByStep({ to, from }: { to: string; from: string }) 'synthetics.step.status': 'failed', }, }, + { + term: { + 'observer.geo.name': selectedLocation?.label, + }, + }, { term: { config_id: monitorId, @@ -67,9 +75,14 @@ export function useFailedTestByStep({ to, from }: { to: string; from: string }) }, }); - const { data, loading } = useEsSearch(params, [lastRefresh, monitorId], { - name: `getFailedTestsByStep/${monitorId}`, - }); + const { data, loading } = useReduxEsSearch( + params, + [lastRefresh, monitorId], + { + name: `getFailedTestsByStep/${monitorId}`, + isRequestReady: !!selectedLocation, + } + ); return useMemo(() => { const total = data?.hits.total.value; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx index dcecbb5f9df8a..6f6052af64a3f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/hooks/use_monitor_errors.tsx @@ -5,9 +5,10 @@ * 2.0. */ -import { useEsSearch, useTimeZone } from '@kbn/observability-plugin/public'; +import { useTimeZone } from '@kbn/observability-plugin/public'; import { useParams } from 'react-router-dom'; import { useMemo } from 'react'; +import { useSelectedLocation } from './use_selected_location'; import { PingState } from '../../../../../../common/runtime_types'; import { EXCLUDE_RUN_ONCE_FILTER, @@ -16,6 +17,7 @@ import { import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; import { useSyntheticsRefreshContext } from '../../../contexts'; import { useGetUrlParams } from '../../../hooks'; +import { useReduxEsSearch } from '../../../hooks/use_redux_es_search'; export function useMonitorErrors(monitorIdArg?: string) { const { lastRefresh } = useSyntheticsRefreshContext(); @@ -24,9 +26,11 @@ export function useMonitorErrors(monitorIdArg?: string) { const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); + const selectedLocation = useSelectedLocation(); + const timeZone = useTimeZone(); - const { data, loading } = useEsSearch( + const { data, loading } = useReduxEsSearch( { index: SYNTHETICS_INDEX_PATTERN, body: { @@ -55,6 +59,11 @@ export function useMonitorErrors(monitorIdArg?: string) { config_id: monitorIdArg ?? monitorId, }, }, + { + term: { + 'observer.geo.name': selectedLocation?.label, + }, + }, ], }, }, @@ -79,7 +88,7 @@ export function useMonitorErrors(monitorIdArg?: string) { }, }, [lastRefresh, monitorId, monitorIdArg, dateRangeStart, dateRangeEnd], - { name: 'getMonitorErrors' } + { name: 'getMonitorErrors', isRequestReady: Boolean(selectedLocation?.label) } ); return useMemo(() => { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx index 3a736645736f7..b18a3f918332d 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_location.tsx @@ -6,8 +6,9 @@ */ import React, { useCallback } from 'react'; -import { useParams } from 'react-router-dom'; +import { useParams, useRouteMatch } from 'react-router-dom'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { MONITOR_ERRORS_ROUTE, MONITOR_HISTORY_ROUTE } from '../../../../../common/constants'; import { ClientPluginsStart } from '../../../../plugin'; import { PLUGIN } from '../../../../../common/constants/plugin'; import { useSelectedLocation } from './hooks/use_selected_location'; @@ -22,6 +23,9 @@ export const MonitorDetailsLocation = ({ isDisabled }: { isDisabled?: boolean }) const { services } = useKibana(); + const isErrorsTab = useRouteMatch(MONITOR_ERRORS_ROUTE); + const isHistoryTab = useRouteMatch(MONITOR_HISTORY_ROUTE); + return ( { - services.application.navigateToApp(PLUGIN.SYNTHETICS_PLUGIN_ID, { - path: `/monitor/${monitorId}?locationId=${id}`, - }); + if (isErrorsTab) { + services.application.navigateToApp(PLUGIN.SYNTHETICS_PLUGIN_ID, { + path: `/monitor/${monitorId}/errors?locationId=${id}`, + }); + } else if (isHistoryTab) { + services.application.navigateToApp(PLUGIN.SYNTHETICS_PLUGIN_ID, { + path: `/monitor/${monitorId}/history/?locationId=${id}`, + }); + } else { + services.application.navigateToApp(PLUGIN.SYNTHETICS_PLUGIN_ID, { + path: `/monitor/${monitorId}?locationId=${id}`, + }); + } }, - [monitorId, services.application] + [isErrorsTab, isHistoryTab, monitorId, services.application] )} /> ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx index f2a25baaa4f01..438539896fa49 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/errors_list.tsx @@ -115,7 +115,7 @@ export const ErrorsList = ({ name: ERROR_DURATION_LABEL, align: 'right' as const, sortable: true, - render: (value: number, item: PingState) => { + render: (value: string, item: PingState) => { const isActive = isActiveState(item); let activeDuration = 0; if (item.monitor.timespan) { @@ -131,7 +131,7 @@ export const ErrorsList = ({ activeDuration = diff; } } - return {formatTestDuration(value + activeDuration, true)}; + return {formatTestDuration(Number(value) + activeDuration, true)}; }, }, ]; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests_count.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests_count.tsx index 9df548e4614f2..8192142932dc8 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests_count.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/failed_tests_count.tsx @@ -7,6 +7,7 @@ import { useKibana } from '@kbn/kibana-react-plugin/public'; import React from 'react'; +import { useSelectedLocation } from '../hooks/use_selected_location'; import { FAILED_TESTS_LABEL } from './failed_tests'; import { ClientPluginsStart } from '../../../../../plugin'; import { useMonitorQueryId } from '../hooks/use_monitor_query_id'; @@ -18,7 +19,9 @@ export const FailedTestsCount = (time: { to: string; from: string }) => { const monitorId = useMonitorQueryId(); - if (!monitorId) { + const selectedLocation = useSelectedLocation(); + + if (!monitorId || !selectedLocation) { return null; } @@ -30,6 +33,7 @@ export const FailedTestsCount = (time: { to: string; from: string }) => { time, reportDefinitions: { 'monitor.id': [monitorId], + 'observer.geo.name': [selectedLocation?.label], }, dataType: 'synthetics', selectedMetricField: 'monitor_failed_tests', From 227200d3510e033524f8890a8216bd249980418a Mon Sep 17 00:00:00 2001 From: Muhammad Ibragimov <53621505+mibragimov@users.noreply.github.com> Date: Thu, 9 Feb 2023 18:45:50 +0500 Subject: [PATCH 024/203] [Console] Enable `allowJs` and fix type issues (#149379) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/elastic/kibana/issues/144282 ### Summary This PR resolves TS errors when `allowJs` is enabled in `tsconfig.json` for the Console plugin --------- Co-authored-by: Muhammad Ibragimov Co-authored-by: Yulia Čech <6585477+yuliacech@users.noreply.github.com> Co-authored-by: Yulia Cech Co-authored-by: Spencer --- .../application/components/welcome_panel.tsx | 1 - .../console_history/history_viewer.tsx | 1 - .../legacy_core_editor/legacy_core_editor.ts | 5 +- .../mode/{input.js => input.ts} | 38 +++-- .../mode/input_highlight_rules.js | 144 ----------------- .../mode/input_highlight_rules.ts | 148 ++++++++++++++++++ .../mode/{script.js => script.ts} | 22 +-- .../legacy_core_editor/mode/worker/worker.js | 6 +- .../models/sense_editor/sense_editor.ts | 2 - .../public/lib/autocomplete/autocomplete.ts | 3 - .../components/full_request_component.ts | 3 +- .../get_endpoint_from_position.ts | 2 - src/plugins/console/tsconfig.json | 5 - 13 files changed, 187 insertions(+), 193 deletions(-) rename src/plugins/console/public/application/models/legacy_core_editor/mode/{input.js => input.ts} (66%) delete mode 100644 src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js create mode 100644 src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.ts rename src/plugins/console/public/application/models/legacy_core_editor/mode/{script.js => script.ts} (69%) diff --git a/src/plugins/console/public/application/components/welcome_panel.tsx b/src/plugins/console/public/application/components/welcome_panel.tsx index 9b2741e4c30e0..a17d17eac8930 100644 --- a/src/plugins/console/public/application/components/welcome_panel.tsx +++ b/src/plugins/console/public/application/components/welcome_panel.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -// @ts-ignore import { EuiFlyout, EuiFlyoutHeader, diff --git a/src/plugins/console/public/application/containers/console_history/history_viewer.tsx b/src/plugins/console/public/application/containers/console_history/history_viewer.tsx index 11f4b0a99a993..f4af349744531 100644 --- a/src/plugins/console/public/application/containers/console_history/history_viewer.tsx +++ b/src/plugins/console/public/application/containers/console_history/history_viewer.tsx @@ -12,7 +12,6 @@ import { i18n } from '@kbn/i18n'; import { DevToolsSettings } from '../../../services'; import { subscribeResizeChecker } from '../editor/legacy/subscribe_console_resize_checker'; -// @ts-ignore import * as InputMode from '../../models/legacy_core_editor/mode/input'; const inputMode = new InputMode.Mode(); import * as editor from '../../models/legacy_core_editor'; diff --git a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts index 5c041a95e216f..f8e411fabbb55 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts +++ b/src/plugins/console/public/application/models/legacy_core_editor/legacy_core_editor.ts @@ -21,8 +21,6 @@ import { import { AceTokensProvider } from '../../../lib/ace_token_provider'; import * as curl from '../sense_editor/curl'; import smartResize from './smart_resize'; - -// @ts-ignore import * as InputMode from './mode/input'; const _AceRange = ace.acequire('ace/range').Range; @@ -40,6 +38,9 @@ export class LegacyCoreEditor implements CoreEditor { this.editor.setShowPrintMargin(false); const session = this.editor.getSession(); + // @ts-expect-error + // ignore ts error here due to type definition mistake in brace for setMode(mode: string): void; + // this method accepts string or SyntaxMode which is an object. See https://github.com/ajaxorg/ace/blob/13dc911dbc0ea31ca343d5744b3f472767458fc3/ace.d.ts#L467 session.setMode(new InputMode.Mode()); (session as unknown as { setFoldStyle: (style: string) => void }).setFoldStyle('markbeginend'); session.setTabSize(2); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.ts similarity index 66% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/input.js rename to src/plugins/console/public/application/models/legacy_core_editor/mode/input.ts index 6c58036717e74..f27f6f1845020 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input.ts @@ -10,7 +10,6 @@ import ace from 'brace'; import { workerModule } from './worker'; import { ScriptMode } from './script'; -const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; @@ -21,24 +20,26 @@ const AceTokenizer = ace.acequire('ace/tokenizer').Tokenizer; import { InputHighlightRules } from './input_highlight_rules'; -export function Mode() { - this.$tokenizer = new AceTokenizer(new InputHighlightRules().getRules()); - this.$outdent = new MatchingBraceOutdent(); - this.$behaviour = new CstyleBehaviour(); - this.foldingRules = new CStyleFoldMode(); - this.createModeDelegates({ - 'script-': ScriptMode, - }); +export class Mode extends TextMode { + constructor() { + super(); + this.$tokenizer = new AceTokenizer(new InputHighlightRules().getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); + this.createModeDelegates({ + 'script-': ScriptMode, + }); + } } -oop.inherits(Mode, TextMode); -(function () { +(function (this: Mode) { this.getCompletions = function () { // autocomplete is done by the autocomplete module. return []; }; - this.getNextLineIndent = function (state, line, tab) { + this.getNextLineIndent = function (state: string, line: string, tab: string) { let indent = this.$getIndent(line); if (state !== 'string_literal') { @@ -51,21 +52,24 @@ oop.inherits(Mode, TextMode); return indent; }; - this.checkOutdent = function (state, line, input) { + this.checkOutdent = function (state: unknown, line: string, input: string) { return this.$outdent.checkOutdent(line, input); }; - this.autoOutdent = function (state, doc, row) { + this.autoOutdent = function (state: unknown, doc: string, row: string) { this.$outdent.autoOutdent(doc, row); }; - this.createWorker = function (session) { + this.createWorker = function (session: { + getDocument: () => string; + setAnnotations: (arg0: unknown) => void; + }) { const worker = new WorkerClient(['ace', 'sense_editor'], workerModule, 'SenseWorker'); worker.attachToDocument(session.getDocument()); - worker.on('error', function (e) { + worker.on('error', function (e: { data: unknown }) { session.setAnnotations([e.data]); }); - worker.on('ok', function (anno) { + worker.on('ok', function (anno: { data: unknown }) { session.setAnnotations(anno.data); }); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js deleted file mode 100644 index bb3efc0834694..0000000000000 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.js +++ /dev/null @@ -1,144 +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 ace from 'brace'; -import { addXJsonToRules } from '@kbn/ace'; - -export function addEOL(tokens, reg, nextIfEOL, normalNext) { - if (typeof reg === 'object') { - reg = reg.source; - } - return [ - { token: tokens.concat(['whitespace']), regex: reg + '(\\s*)$', next: nextIfEOL }, - { token: tokens, regex: reg, next: normalNext }, - ]; -} - -export function mergeTokens(/* ... */) { - return [].concat.apply([], arguments); -} - -const oop = ace.acequire('ace/lib/oop'); -const { TextHighlightRules } = ace.acequire('ace/mode/text_highlight_rules'); - -export function InputHighlightRules() { - // regexp must not have capturing parentheses. Use (?:) instead. - // regexps are ordered -> the first match is used - /*jshint -W015 */ - this.$rules = { - 'start-sql': [ - { token: 'whitespace', regex: '\\s+' }, - { token: 'paren.lparen', regex: '{', next: 'json-sql', push: true }, - { regex: '', next: 'start' }, - ], - start: mergeTokens( - [ - { token: 'warning', regex: '#!.*$' }, - { include: 'comments' }, - { token: 'paren.lparen', regex: '{', next: 'json', push: true }, - ], - addEOL(['method'], /([a-zA-Z]+)/, 'start', 'method_sep'), - [ - { - token: 'whitespace', - regex: '\\s+', - }, - { - token: 'text', - regex: '.+?', - }, - ] - ), - method_sep: mergeTokens( - addEOL( - ['whitespace', 'url.protocol_host', 'url.slash'], - /(\s+)(https?:\/\/[^?\/,]+)(\/)/, - 'start', - 'url' - ), - addEOL(['whitespace', 'variable.template'], /(\s+)(\${\w+})/, 'start', 'url'), - addEOL(['whitespace', 'url.protocol_host'], /(\s+)(https?:\/\/[^?\/,]+)/, 'start', 'url'), - addEOL(['whitespace', 'url.slash'], /(\s+)(\/)/, 'start', 'url'), - addEOL(['whitespace'], /(\s+)/, 'start', 'url') - ), - url: mergeTokens( - addEOL(['variable.template'], /(\${\w+})/, 'start'), - addEOL(['url.part'], /(_sql)/, 'start-sql', 'url-sql'), - addEOL(['url.part'], /([^?\/,\s]+)/, 'start'), - addEOL(['url.comma'], /(,)/, 'start'), - addEOL(['url.slash'], /(\/)/, 'start'), - addEOL(['url.questionmark'], /(\?)/, 'start', 'urlParams'), - addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start') - ), - urlParams: mergeTokens( - addEOL(['url.param', 'url.equal', 'variable.template'], /([^&=]+)(=)(\${\w+})/, 'start'), - addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start'), - addEOL(['url.param'], /([^&=]+)/, 'start'), - addEOL(['url.amp'], /(&)/, 'start'), - addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start') - ), - 'url-sql': mergeTokens( - addEOL(['url.part'], /([^?\/,\s]+)/, 'start-sql'), - addEOL(['url.comma'], /(,)/, 'start-sql'), - addEOL(['url.slash'], /(\/)/, 'start-sql'), - addEOL(['url.questionmark'], /(\?)/, 'start-sql', 'urlParams-sql') - ), - 'urlParams-sql': mergeTokens( - addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start-sql'), - addEOL(['url.param'], /([^&=]+)/, 'start-sql'), - addEOL(['url.amp'], /(&)/, 'start-sql') - ), - /** - * Each key in this.$rules considered to be a state in state machine. Regular expressions define the tokens for the current state, as well as the transitions into another state. - * See for more details https://cloud9-sdk.readme.io/docs/highlighting-rules#section-defining-states - * * - * Define a state for comments, these comment rules then can be included in other states. E.g. in 'start' and 'json' states by including { include: 'comments' } - * This will avoid duplicating the same rules in other states - */ - comments: [ - { - // Capture a line comment, indicated by # - token: ['comment.punctuation', 'comment.line'], - regex: /(#)(.*$)/, - }, - { - // Begin capturing a block comment, indicated by /* - token: 'comment.punctuation', - regex: /\/\*/, - push: [ - { - // Finish capturing a block comment, indicated by */ - token: 'comment.punctuation', - regex: /\*\//, - next: 'pop', - }, - { - defaultToken: 'comment.block', - }, - ], - }, - { - // Capture a line comment, indicated by // - token: ['comment.punctuation', 'comment.line'], - regex: /(\/\/)(.*$)/, - }, - ], - }; - - addXJsonToRules(this); - // Add comment rules to json rule set - this.$rules.json.unshift({ include: 'comments' }); - - this.$rules.json.unshift({ token: 'variable.template', regex: /("\${\w+}")/ }); - - if (this.constructor === InputHighlightRules) { - this.normalizeRules(); - } -} - -oop.inherits(InputHighlightRules, TextHighlightRules); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.ts b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.ts new file mode 100644 index 0000000000000..acf4b091c6b0f --- /dev/null +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/input_highlight_rules.ts @@ -0,0 +1,148 @@ +/* + * Copyright 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 ace from 'brace'; +import { addXJsonToRules } from '@kbn/ace'; + +type Token = + | string + | { token?: string; regex?: string; next?: string; push?: boolean; include?: string }; + +export function addEOL( + tokens: Token[], + reg: string | RegExp, + nextIfEOL: string, + normalNext?: string +) { + if (typeof reg === 'object') { + reg = reg.source; + } + return [ + { token: tokens.concat(['whitespace']), regex: reg + '(\\s*)$', next: nextIfEOL }, + { token: tokens, regex: reg, next: normalNext }, + ]; +} + +export const mergeTokens = (...args: any[]) => [].concat.apply([], args); + +const TextHighlightRules = ace.acequire('ace/mode/text_highlight_rules').TextHighlightRules; + +export class InputHighlightRules extends TextHighlightRules { + constructor() { + super(); + this.$rules = { + 'start-sql': [ + { token: 'whitespace', regex: '\\s+' }, + { token: 'paren.lparen', regex: '{', next: 'json-sql', push: true }, + { regex: '', next: 'start' }, + ], + start: mergeTokens( + [ + { token: 'warning', regex: '#!.*$' }, + { include: 'comments' }, + { token: 'paren.lparen', regex: '{', next: 'json', push: true }, + ], + addEOL(['method'], /([a-zA-Z]+)/, 'start', 'method_sep'), + [ + { + token: 'whitespace', + regex: '\\s+', + }, + { + token: 'text', + regex: '.+?', + }, + ] + ), + method_sep: mergeTokens( + addEOL( + ['whitespace', 'url.protocol_host', 'url.slash'], + /(\s+)(https?:\/\/[^?\/,]+)(\/)/, + 'start', + 'url' + ), + addEOL(['whitespace', 'variable.template'], /(\s+)(\${\w+})/, 'start', 'url'), + addEOL(['whitespace', 'url.protocol_host'], /(\s+)(https?:\/\/[^?\/,]+)/, 'start', 'url'), + addEOL(['whitespace', 'url.slash'], /(\s+)(\/)/, 'start', 'url'), + addEOL(['whitespace'], /(\s+)/, 'start', 'url') + ), + url: mergeTokens( + addEOL(['variable.template'], /(\${\w+})/, 'start'), + addEOL(['url.part'], /(_sql)/, 'start-sql', 'url-sql'), + addEOL(['url.part'], /([^?\/,\s]+)/, 'start'), + addEOL(['url.comma'], /(,)/, 'start'), + addEOL(['url.slash'], /(\/)/, 'start'), + addEOL(['url.questionmark'], /(\?)/, 'start', 'urlParams'), + addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start') + ), + urlParams: mergeTokens( + addEOL(['url.param', 'url.equal', 'variable.template'], /([^&=]+)(=)(\${\w+})/, 'start'), + addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start'), + addEOL(['url.param'], /([^&=]+)/, 'start'), + addEOL(['url.amp'], /(&)/, 'start'), + addEOL(['whitespace', 'comment.punctuation', 'comment.line'], /(\s+)(\/\/)(.*$)/, 'start') + ), + 'url-sql': mergeTokens( + addEOL(['url.part'], /([^?\/,\s]+)/, 'start-sql'), + addEOL(['url.comma'], /(,)/, 'start-sql'), + addEOL(['url.slash'], /(\/)/, 'start-sql'), + addEOL(['url.questionmark'], /(\?)/, 'start-sql', 'urlParams-sql') + ), + 'urlParams-sql': mergeTokens( + addEOL(['url.param', 'url.equal', 'url.value'], /([^&=]+)(=)([^&]*)/, 'start-sql'), + addEOL(['url.param'], /([^&=]+)/, 'start-sql'), + addEOL(['url.amp'], /(&)/, 'start-sql') + ), + /** + * Each key in this.$rules considered to be a state in state machine. Regular expressions define the tokens for the current state, as well as the transitions into another state. + * See for more details https://cloud9-sdk.readme.io/docs/highlighting-rules#section-defining-states + * * + * Define a state for comments, these comment rules then can be included in other states. E.g. in 'start' and 'json' states by including { include: 'comments' } + * This will avoid duplicating the same rules in other states + */ + comments: [ + { + // Capture a line comment, indicated by # + token: ['comment.punctuation', 'comment.line'], + regex: /(#)(.*$)/, + }, + { + // Begin capturing a block comment, indicated by /* + token: 'comment.punctuation', + regex: /\/\*/, + push: [ + { + // Finish capturing a block comment, indicated by */ + token: 'comment.punctuation', + regex: /\*\//, + next: 'pop', + }, + { + defaultToken: 'comment.block', + }, + ], + }, + { + // Capture a line comment, indicated by // + token: ['comment.punctuation', 'comment.line'], + regex: /(\/\/)(.*$)/, + }, + ], + }; + + addXJsonToRules(this, 'json'); + // Add comment rules to json rule set + this.$rules.json.unshift({ include: 'comments' }); + + this.$rules.json.unshift({ token: 'variable.template', regex: /("\${\w+}")/ }); + + if (this instanceof InputHighlightRules) { + this.normalizeRules(); + } + } +} diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.ts similarity index 69% rename from src/plugins/console/public/application/models/legacy_core_editor/mode/script.js rename to src/plugins/console/public/application/models/legacy_core_editor/mode/script.ts index 17b892ec4e61d..401a739e6a28c 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/script.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/script.ts @@ -9,25 +9,25 @@ import ace from 'brace'; import { ScriptHighlightRules } from '@kbn/ace'; -const oop = ace.acequire('ace/lib/oop'); const TextMode = ace.acequire('ace/mode/text').Mode; const MatchingBraceOutdent = ace.acequire('ace/mode/matching_brace_outdent').MatchingBraceOutdent; const CstyleBehaviour = ace.acequire('ace/mode/behaviour/cstyle').CstyleBehaviour; const CStyleFoldMode = ace.acequire('ace/mode/folding/cstyle').FoldMode; ace.acequire('ace/tokenizer'); -export function ScriptMode() { - this.$outdent = new MatchingBraceOutdent(); - this.$behaviour = new CstyleBehaviour(); - this.foldingRules = new CStyleFoldMode(); +export class ScriptMode extends TextMode { + constructor() { + super(); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); + } } -oop.inherits(ScriptMode, TextMode); - -(function () { +(function (this: ScriptMode) { this.HighlightRules = ScriptHighlightRules; - this.getNextLineIndent = function (state, line, tab) { + this.getNextLineIndent = function (state: unknown, line: string, tab: string) { let indent = this.$getIndent(line); const match = line.match(/^.*[\{\[]\s*$/); if (match) { @@ -37,11 +37,11 @@ oop.inherits(ScriptMode, TextMode); return indent; }; - this.checkOutdent = function (state, line, input) { + this.checkOutdent = function (state: unknown, line: string, input: string) { return this.$outdent.checkOutdent(line, input); }; - this.autoOutdent = function (state, doc, row) { + this.autoOutdent = function (state: unknown, doc: string, row: string) { this.$outdent.autoOutdent(doc, row); }; }.call(ScriptMode.prototype)); diff --git a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/worker.js b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/worker.js index c7938437164f7..fa03617f5824f 100644 --- a/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/worker.js +++ b/src/plugins/console/public/application/models/legacy_core_editor/mode/worker/worker.js @@ -47,8 +47,7 @@ (hence the redefining of everything). It is based on the javascript mode from the brace distro. */ - -(function (window) { +function init(window) { function resolveModuleId(id, paths) { for (let testPath = id, tail = ''; testPath;) { let alias = paths[testPath]; @@ -235,7 +234,8 @@ } }; } -}(this)), +} +init(this); ace.define('ace/lib/oop', ['require', 'exports', 'module'], function ( acequire, exports 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 ac2205205ab46..f42cce75a4c54 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 @@ -12,8 +12,6 @@ import { XJson } from '@kbn/es-ui-shared-plugin/public'; import RowParser from '../../../lib/row_parser'; import * as utils from '../../../lib/utils'; - -// @ts-ignore import { constructUrl } from '../../../lib/es/es'; import { CoreEditor, Position, Range } from '../../../types'; diff --git a/src/plugins/console/public/lib/autocomplete/autocomplete.ts b/src/plugins/console/public/lib/autocomplete/autocomplete.ts index b24767b361d7e..71cca78926459 100644 --- a/src/plugins/console/public/lib/autocomplete/autocomplete.ts +++ b/src/plugins/console/public/lib/autocomplete/autocomplete.ts @@ -15,7 +15,6 @@ import { getGlobalAutocompleteComponents, getTopLevelUrlCompleteComponents, getUnmatchedEndpointComponents, - // @ts-ignore } from '../kb/kb'; import { createTokenIterator } from '../../application/factories'; @@ -24,10 +23,8 @@ import type RowParser from '../row_parser'; import * as utils from '../utils'; -// @ts-ignore import { populateContext } from './engine'; import type { AutoCompleteContext, DataAutoCompleteRulesOneOf, ResultTerm } from './types'; -// @ts-ignore import { URL_PATH_END_MARKER } from './components'; let lastEvaluatedToken: Token | null = null; diff --git a/src/plugins/console/public/lib/autocomplete/components/full_request_component.ts b/src/plugins/console/public/lib/autocomplete/components/full_request_component.ts index 64aefa7b4a121..33af4e71abec1 100644 --- a/src/plugins/console/public/lib/autocomplete/components/full_request_component.ts +++ b/src/plugins/console/public/lib/autocomplete/components/full_request_component.ts @@ -6,11 +6,10 @@ * Side Public License, v 1. */ -// @ts-ignore import { ConstantComponent } from './constant_component'; export class FullRequestComponent extends ConstantComponent { - private readonly name: string; + readonly name: string; constructor(name: string, parent: unknown, private readonly template: string) { super(name, parent); this.name = name; diff --git a/src/plugins/console/public/lib/autocomplete/get_endpoint_from_position.ts b/src/plugins/console/public/lib/autocomplete/get_endpoint_from_position.ts index fe24492df0e7b..579e652615487 100644 --- a/src/plugins/console/public/lib/autocomplete/get_endpoint_from_position.ts +++ b/src/plugins/console/public/lib/autocomplete/get_endpoint_from_position.ts @@ -10,9 +10,7 @@ import { CoreEditor, Position } from '../../types'; import { getCurrentMethodAndTokenPaths } from './autocomplete'; import type RowParser from '../row_parser'; -// @ts-ignore import { getTopLevelUrlCompleteComponents } from '../kb/kb'; -// @ts-ignore import { populateContext } from './engine'; export function getEndpointFromPosition(editor: CoreEditor, pos: Position, parser: RowParser) { diff --git a/src/plugins/console/tsconfig.json b/src/plugins/console/tsconfig.json index 43b94e47eedd4..4d1d508078eec 100644 --- a/src/plugins/console/tsconfig.json +++ b/src/plugins/console/tsconfig.json @@ -2,11 +2,6 @@ "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", - // there is still a decent amount of JS in this plugin and we are taking - // advantage of the fact that TS doesn't know the types of that code and - // gives us `any`. Once that code is converted to .ts we can remove this - // and allow TS to infer types from any JS file imported. - "allowJs": false }, "include": ["common/**/*", "public/**/*", "server/**/*"], "kbn_references": [ From e2b80196def648f501a27f4e924fdf0fe8cb5790 Mon Sep 17 00:00:00 2001 From: Elastic Machine Date: Fri, 10 Feb 2023 00:35:05 +1030 Subject: [PATCH 025/203] [main] Sync bundled packages with Package Storage (#150646) Automated by https://internal-ci.elastic.co/job/package_storage/job/sync-bundled-packages-job/job/main/1722/ Co-authored-by: apmmachine Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- fleet_packages.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fleet_packages.json b/fleet_packages.json index 109fa8e5da7dc..0f148d6899bbc 100644 --- a/fleet_packages.json +++ b/fleet_packages.json @@ -20,7 +20,7 @@ [ { "name": "apm", - "version": "8.7.0-preview-1675078021", + "version": "8.8.0-preview-1675842740", "forceAlignStackVersion": true }, { @@ -29,7 +29,7 @@ }, { "name": "endpoint", - "version": "8.7.0-next" + "version": "8.7.0" }, { "name": "fleet_server", From 68dbac0c4e6149bcf5f9ba2b3316d39834a97374 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 9 Feb 2023 15:27:33 +0100 Subject: [PATCH 026/203] [Synthetics] Fix getting started condition (#150548) Fixes https://github.com/elastic/kibana/issues/150077 --- .../default_status_alert.journey.ts | 2 +- .../synthetics/overview_search.journey.ts | 89 ++++++++++--------- .../monitor_details/monitor_details_page.tsx | 7 +- .../monitors_page/common/search_field.tsx | 2 +- .../monitors_page/overview/overview_page.tsx | 20 +++-- .../synthetics/state/monitor_details/index.ts | 2 + 6 files changed, 72 insertions(+), 50 deletions(-) diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts index 3da959eefa145..3e1c7a8430afb 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/alert_rules/default_status_alert.journey.ts @@ -193,7 +193,7 @@ journey(`DefaultStatusAlert`, async ({ page, params }) => { }); await page.click(byTestId('alert-status-filter-active-button')); - await page.waitForTimeout(5 * 1000); + await syntheticsApp.waitForLoadingToFinish(); await page.click('[aria-label="View in app"]'); await page.click(byTestId('syntheticsMonitorOverviewTab')); diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_search.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_search.journey.ts index c2db2afec4760..289b434b9e2c9 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_search.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_search.journey.ts @@ -7,6 +7,7 @@ import { before, expect, journey, step } from '@elastic/synthetics'; import { recordVideo } from '@kbn/observability-plugin/e2e/record_video'; +import { RetryService } from '@kbn/ftr-common-functional-services'; import { addTestMonitor, cleanTestMonitors, @@ -17,6 +18,8 @@ import { syntheticsAppPageProvider } from '../../page_objects/synthetics/synthet journey('Overview Search', async ({ page, params }) => { recordVideo(page); + const retry: RetryService = params.getService('retry'); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); const elasticJourney = 'Elastic journey'; const cnnJourney = 'CNN journey'; @@ -98,47 +101,53 @@ journey('Overview Search', async ({ page, params }) => { await page.waitForSelector(`text=${elasticJourney}`); await page.waitForSelector(`text=${cnnJourney}`); await page.waitForSelector(`text=${googleJourney}`); - await page.click('[aria-label="Clear input"]'); - await page.focus('[data-test-subj="syntheticsOverviewSearchInput"]'); - await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'dev', { delay: 300 }); - await page.waitForSelector(`text=${elasticJourney}`); - expect(await elastic.count()).toBe(1); - expect(await cnn.count()).toBe(0); - expect(await google.count()).toBe(0); - await page.click('[aria-label="Clear input"]'); - await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'qa', { delay: 300 }); - await page.waitForSelector(`text=${cnnJourney}`); - expect(await elastic.count()).toBe(0); - expect(await cnn.count()).toBe(1); - expect(await google.count()).toBe(0); - await page.click('[aria-label="Clear input"]'); - await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'staging', { delay: 300 }); - await page.waitForSelector(`text=${googleJourney}`); - expect(await elastic.count()).toBe(0); - expect(await cnn.count()).toBe(0); - expect(await google.count()).toBe(1); - await page.click('[aria-label="Clear input"]'); - await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'prod', { - delay: 300, - }); - await page.waitForSelector(`text=${gmailJourney}`); - expect(await elastic.count()).toBe(0); - expect(await cnn.count()).toBe(0); - expect(await google.count()).toBe(0); - expect(await gmail.count()).toBe(1); - await page.click('[aria-label="Clear input"]'); - await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'tag', { - delay: 300, - }); - await page.waitForSelector(`text=${elasticJourney}`); - await page.waitForSelector(`text=${cnnJourney}`); - await page.waitForSelector(`text=${googleJourney}`); - await page.waitForSelector(`text=${gmailJourney}`); + await retry.tryForTime(60 * 1000, async () => { + await page.click('[aria-label="Clear input"]'); + await page.focus('[data-test-subj="syntheticsOverviewSearchInput"]'); + await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'dev', { delay: 300 }); + await page.waitForSelector(`text=${elasticJourney}`); + expect(await elastic.count()).toBe(1); + expect(await cnn.count()).toBe(0); + expect(await google.count()).toBe(0); + await page.click('[aria-label="Clear input"]'); + await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'qa', { delay: 300 }); + await page.waitForSelector(`text=${cnnJourney}`); + expect(await elastic.count()).toBe(0); + expect(await cnn.count()).toBe(1); + expect(await google.count()).toBe(0); + await page.click('[aria-label="Clear input"]'); + await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'staging', { + delay: 300, + }); + await page.waitForSelector(`text=${googleJourney}`); + expect(await elastic.count()).toBe(0); + expect(await cnn.count()).toBe(0); + expect(await google.count()).toBe(1); + await page.click('[aria-label="Clear input"]'); + await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'prod', { + delay: 300, + }); + await page.waitForSelector(`text=${gmailJourney}`); + await retry.try(async () => { + expect(await elastic.count()).toBe(0); + expect(await cnn.count()).toBe(0); + expect(await google.count()).toBe(0); + expect(await gmail.count()).toBe(1); + }); + await page.click('[aria-label="Clear input"]'); + await page.type('[data-test-subj="syntheticsOverviewSearchInput"]', 'tag', { + delay: 300, + }); + await page.waitForSelector(`text=${elasticJourney}`); + await page.waitForSelector(`text=${cnnJourney}`); + await page.waitForSelector(`text=${googleJourney}`); + await page.waitForSelector(`text=${gmailJourney}`); - expect(await elastic.count()).toBe(1); - expect(await cnn.count()).toBe(1); - expect(await google.count()).toBe(1); - expect(await gmail.count()).toBe(1); + expect(await elastic.count()).toBe(1); + expect(await cnn.count()).toBe(1); + expect(await google.count()).toBe(1); + expect(await gmail.count()).toBe(1); + }); }); step('searches by url and host', async () => { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx index fa279a4d64a4c..beb7c6e9585d4 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_details_page.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { Redirect, useParams } from 'react-router-dom'; import { MONITOR_NOT_FOUND_ROUTE } from '../../../../../common/constants'; +import { ConfigKey } from '../../../../../common/runtime_types'; import { useMonitorListBreadcrumbs } from '../monitors_page/hooks/use_breadcrumbs'; import { useSelectedMonitor } from './hooks/use_selected_monitor'; @@ -19,7 +20,11 @@ export const MonitorDetailsPage: React.FC<{ children: React.ReactElement }> = ({ useMonitorListBreadcrumbs(monitor ? [{ text: monitor?.name ?? '' }] : []); - if (error?.body.statusCode === 404) { + if ( + error?.body.statusCode === 404 && + (error.getPayload as { monitorId: string })?.monitorId === monitorId && + monitor?.[ConfigKey.CONFIG_ID] !== monitorId + ) { return ; } return children; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/search_field.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/search_field.tsx index 1c93669fb4112..01e9beda8a7e1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/search_field.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/search_field.tsx @@ -30,7 +30,7 @@ export function SearchField() { // Hydrate search input const hasInputChangedRef = useRef(false); useEffect(() => { - if (query && query !== search && !hasInputChangedRef.current) { + if (query !== search && !hasInputChangedRef.current) { setSearch(query); } diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview_page.tsx index edf14fe3dfbfd..158061692d475 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview_page.tsx @@ -16,7 +16,7 @@ import { useSyntheticsRefreshContext } from '../../../contexts/synthetics_refres import { fetchMonitorOverviewAction, quietFetchOverviewAction, - selectOverviewPageState, + selectOverviewState, selectServiceLocationsState, } from '../../../state'; import { getServiceLocations } from '../../../state/service_locations'; @@ -42,7 +42,6 @@ export const OverviewPage: React.FC = () => { const { lastRefresh } = useSyntheticsRefreshContext(); const { search } = useLocation(); - const pageState = useSelector(selectOverviewPageState); const { loading: locationsLoading, locationsLoaded } = useSelector(selectServiceLocationsState); useEffect(() => { @@ -57,10 +56,15 @@ export const OverviewPage: React.FC = () => { } = useEnablement(); const { - syntheticsMonitors, + data: { monitors }, + pageState, + } = useSelector(selectOverviewState); + + const { loading: monitorsLoading, loaded: monitorsLoaded, handleFilterChange, + absoluteTotal, } = useMonitorList(); // fetch overview for all other page state changes @@ -80,8 +84,7 @@ export const OverviewPage: React.FC = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [dispatch, lastRefresh]); - const hasNoMonitors = - !search && !enablementLoading && monitorsLoaded && syntheticsMonitors.length === 0; + const hasNoMonitors = !search && !enablementLoading && monitorsLoaded && absoluteTotal === 0; if (hasNoMonitors && !monitorsLoading && isEnabled) { return ; @@ -91,6 +94,8 @@ export const OverviewPage: React.FC = () => { return ; } + const noMonitorFound = monitorsLoaded && monitors?.length === 0; + return ( <> @@ -105,7 +110,7 @@ export const OverviewPage: React.FC = () => { - {Boolean(!monitorsLoaded || syntheticsMonitors?.length > 0) && ( + {!noMonitorFound ? ( <> @@ -121,8 +126,9 @@ export const OverviewPage: React.FC = () => { + ) : ( + )} - {monitorsLoaded && syntheticsMonitors?.length === 0 && } ); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts index c8af30331cdf1..ec1abe5401dc2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/monitor_details/index.ts @@ -88,10 +88,12 @@ export const monitorDetailsReducer = createReducer(initialState, (builder) => { .addCase(getMonitorAction.get, (state, action) => { state.syntheticsMonitorDispatchedAt = action.meta.dispatchedAt; state.syntheticsMonitorLoading = true; + state.error = null; }) .addCase(getMonitorAction.success, (state, action) => { state.syntheticsMonitor = action.payload; state.syntheticsMonitorLoading = false; + state.error = null; }) .addCase(getMonitorAction.fail, (state, action) => { state.error = action.payload; From 30745e236a95f3ccd3d8e2ac1240e826860a68af Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Thu, 9 Feb 2023 09:32:14 -0500 Subject: [PATCH 027/203] [Fleet] Ensure react-query devtools `initialIsOpen` is false (#150702) ## Summary Left a bit of testing code here where I had devtools open all the time - this PR ensures they're closed by default on Fleet/Integrations pages. --- x-pack/plugins/fleet/public/applications/fleet/app.tsx | 2 +- x-pack/plugins/fleet/public/applications/integrations/app.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index 3f657ed174483..f62ae6100ce66 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -262,7 +262,7 @@ export const FleetAppContext: React.FC<{ - + diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index c9e0d97a672b5..44e2dc7c7abe3 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -84,7 +84,7 @@ export const IntegrationsAppContext: React.FC<{ - + From 38cb7b3fd2d05ca20fa3e6538a3430caaf738c6f Mon Sep 17 00:00:00 2001 From: Shahzad Date: Thu, 9 Feb 2023 15:40:52 +0100 Subject: [PATCH 028/203] [Synthetics] Fix step details current step edge case (#150687) ## Summary Fixes https://github.com/elastic/kibana/issues/150612 --- .../components/step_details_page/step_detail_page.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx index 4f008ceac4f35..bccfb041066a3 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/step_details_page/step_detail_page.tsx @@ -34,10 +34,6 @@ export const StepDetailPage = () => { useStepDetailsBreadcrumbs(); - const activeStep = data?.steps?.find( - (step) => step.synthetics?.step?.index === Number(stepIndex) - ); - const dispatch = useDispatch(); useEffect(() => { @@ -51,7 +47,7 @@ export const StepDetailPage = () => { return ( <> - + {data?.details?.journey?.config_id && ( { )} From fc2e95cab167b5ac16394f5f60569934509da430 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Thu, 9 Feb 2023 15:42:13 +0100 Subject: [PATCH 029/203] [Enterprise Search] Fix some minor React errors (#150700) ## Summary This fixes two minor React errors that were showing up in the console. --- .../components/new_index/button_group.tsx | 1 + .../search_index/name_and_description_stats.tsx | 5 ++++- .../search_index/pipelines/pipeline_json_badges.tsx | 10 +++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/button_group.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/button_group.tsx index 1bcaa80deef6d..6722ac17443ae 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/button_group.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/new_index/button_group.tsx @@ -46,6 +46,7 @@ export const ButtonGroup: React.FC = ({ onChange, options, selected }) => 'buttonGroupOption--selected': isSelected, })} grow={false} + key={index} onClick={() => { onChange(option); }} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/name_and_description_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/name_and_description_stats.tsx index 3c5b44f6f571a..236a731b43069 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/name_and_description_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/name_and_description_stats.tsx @@ -52,14 +52,17 @@ export const NameAndDescriptionStats: React.FC = () => { description: setIsFlyoutVisible(true)} />, isLoading: hideStats, title: indexData.connector.name, + descriptionElement: 'div', + titleElement: 'div', }, { description: ( setIsFlyoutVisible(true)} /> ), + descriptionElement: 'div', isLoading: hideStats, title: {indexData.connector.description || ''}, - titleElement: 'p', + titleElement: 'div', }, ]; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_json_badges.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_json_badges.tsx index 9a690ab437dab..16365012003b0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_json_badges.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipeline_json_badges.tsx @@ -131,17 +131,17 @@ export const PipelineJSONBadges: React.FC = () => { } const badges: JSX.Element[] = []; if (isManagedPipeline(pipeline)) { - badges.push(); + badges.push(); } else { - badges.push(); + badges.push(); } if (pipelineName === DEFAULT_PIPELINE_NAME) { - badges.push(); + badges.push(); } if (pipelineName?.endsWith('@ml-inference')) { - badges.push(); + badges.push(); } else if (pipelineName?.includes(indexName)) { - badges.push(); + badges.push(); } return {badges}; }; From 3cd7f429e6d037992f48abdeda187aa8974c8a2c Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Thu, 9 Feb 2023 15:57:00 +0100 Subject: [PATCH 030/203] fix `src/plugins/content_management` codeowners (#150707) --- .github/CODEOWNERS | 2 +- src/plugins/content_management/kibana.jsonc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 695dc14ff8d08..0491048bcf81b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -583,7 +583,7 @@ packages/kbn-config-mocks @elastic/kibana-core packages/kbn-config-schema @elastic/kibana-core src/plugins/console @elastic/platform-deployment-management packages/content-management/content_editor @elastic/appex-sharedux -src/plugins/content_management @elastic/kibana-global-experience +src/plugins/content_management @elastic/appex-sharedux packages/content-management/table_list @elastic/appex-sharedux examples/controls_example @elastic/kibana-presentation src/plugins/controls @elastic/kibana-presentation diff --git a/src/plugins/content_management/kibana.jsonc b/src/plugins/content_management/kibana.jsonc index 550843f22dbce..73878817d9d20 100644 --- a/src/plugins/content_management/kibana.jsonc +++ b/src/plugins/content_management/kibana.jsonc @@ -1,7 +1,7 @@ { "type": "plugin", "id": "@kbn/content-management-plugin", - "owner": "@elastic/kibana-global-experience", + "owner": "@elastic/appex-sharedux", "description": "Content management app", "plugin": { "id": "contentManagement", From c0c023aaa6bf977a8a7a357998d612f04ea2f024 Mon Sep 17 00:00:00 2001 From: Jeramy Soucy Date: Thu, 9 Feb 2023 10:00:02 -0500 Subject: [PATCH 031/203] [Flaky Test] Unskips 'single-namespace types' copy to space tests (#150492) closes #86545 closes #149544 closes #149547 closes #149563 Fixed by PR #149582 - [Flaky test runner on x-pack/test/spaces_api_integration/security_and_spaces](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1880) - [Flaky test runner on x-pack/test/saved_object_api_integration/security_and_spaces](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1888) --- .../test/spaces_api_integration/common/suites/copy_to_space.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 5c519c8ae5b67..4c5ae878bbf6e 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 @@ -770,8 +770,7 @@ export function copyToSpaceTestSuiteFactory(context: FtrProviderContext) { await testDataLoader.deleteFtrSpaces(); }); - // FLAKY: https://github.com/elastic/kibana/issues/86545 - describe.skip('single-namespace types', () => { + describe('single-namespace types', () => { beforeEach(async () => { await testDataLoader.createFtrSavedObjectsData(SPACE_DATA_TO_LOAD); }); From 3b1ff55ac8f4b8817bd60b7762bc701e838b02b2 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Thu, 9 Feb 2023 16:20:11 +0100 Subject: [PATCH 032/203] Address react warnings (#150680) This PR addresses React warnings:
1. When chart is rendered on Discover page

react_devtools_backend.js:4012 Warning: Failed prop type: Invalid prop `children` of type `array` supplied to `PseudoLocaleWrapper`, expected a single ReactElement. at PseudoLocaleWrapper (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:14195:5) at I18nProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:14126:3) at CurrentEuiBreakpointProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:165359:23) at EuiThemeProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:170451:22) at EuiCacheProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:142029:20) at EuiProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:142129:25) at KibanaThemeProvider (http://localhost:5601/qoz/9007199254740991/bundles/plugin/kibanaReact/1.0.0/kibanaReact.plugin.js:4624:3)

2. When Kibana nav is opened

react_devtools_backend.js:4012 Warning: React does not recognize the `dataTestSubj` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `datatestsubj` instead. If you accidentally passed it from a parent component, remove it from the DOM element. at a at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:174472:73 at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:80747:24 at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:174472:73 at EuiButton (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:80550:25) at div at div at EuiCollapsibleNavGroup (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:84295:24) at div at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:174472:73 at EuiFlexItem (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:111981:23) at nav at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:174472:73 at div at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:364444:59 at FocusLockUI (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:360747:71) at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:361650:60 at EuiFocusTrap (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:112986:81) at EuiPortal (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:141607:81) at http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:112245:24 at EuiCollapsibleNav (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:84156:17) at CollapsibleNav (http://localhost:5601/qoz/9007199254740991/bundles/core/core.entry.js:10856:3) at div at EuiHeaderSectionItem (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:121458:26) at div at EuiHeaderSection (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:121399:24) at div at EuiHeader (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:120782:23) at div at header at Header (http://localhost:5601/qoz/9007199254740991/bundles/core/core.entry.js:11177:3) at CurrentEuiBreakpointProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:165359:23) at EuiThemeProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:170451:22) at EuiCacheProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:142029:20) at EuiProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:142129:25) at CoreThemeProvider (http://localhost:5601/qoz/9007199254740991/bundles/core/core.entry.js:21741:3) at EuiContext (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:90101:24) at PseudoLocaleWrapper (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:14195:5) at IntlProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:149376:5) at I18nProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:14126:3) at I18nContext (http://localhost:5601/qoz/9007199254740991/bundles/core/core.entry.js:16388:9) at CoreContextProvider (http://localhost:5601/qoz/9007199254740991/bundles/core/core.entry.js:21669:3)

3. When visiting Home > Try sample data page

Warning: Cannot update a component (`HeaderBreadcrumbs`) while rendering a different component (`TutorialDirectoryUi`). To locate the bad setState() call inside `TutorialDirectoryUi`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render at TutorialDirectoryUi (http://localhost:5601/qoz/9007199254740991/bundles/plugin/home/1.0.0/home.chunk.0.js:13055:5) at InjectIntl (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:149015:7) at Route (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:365503:29) at Switch (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:365709:29) at Router (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:365132:30) at HashRouter (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:364784:35) at PseudoLocaleWrapper (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:14195:5) at IntlProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:149376:5) at I18nProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-src/kbn-ui-shared-deps-src.js:14126:3) at HomeApp (http://localhost:5601/qoz/9007199254740991/bundles/plugin/home/1.0.0/home.chunk.0.js:10827:3) at SampleDataCardKibanaProvider (http://localhost:5601/qoz/9007199254740991/bundles/plugin/home/1.0.0/home.chunk.0.js:6565:3) at SampleDataTabKibanaProvider (http://localhost:5601/qoz/9007199254740991/bundles/plugin/home/1.0.0/home.chunk.0.js:7107:3) at Provider (http://localhost:5601/qoz/9007199254740991/bundles/plugin/kibanaReact/1.0.0/kibanaReact.plugin.js:1794:15) at CurrentEuiBreakpointProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:165359:23) at EuiThemeProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:170451:22) at EuiCacheProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:142029:20) at EuiProvider (http://localhost:5601/qoz/9007199254740991/bundles/kbn-ui-shared-deps-npm/kbn-ui-shared-deps-npm.dll.js:142129:25) at KibanaThemeProvider (http://localhost:5601/qoz/9007199254740991/bundles/plugin/kibanaReact/1.0.0/kibanaReact.plugin.js:4624:3) at div at RedirectAppLinks (http://localhost:5601/qoz/9007199254740991/bundles/plugin/kibanaReact/1.0.0/kibanaReact.plugin.js:1415:3)

--- .../src/ui/header/nav_link.tsx | 2 +- .../xy_chart_renderer.tsx | 2 +- .../components/tutorial_directory.js | 47 ++++++++++++------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/nav_link.tsx b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/nav_link.tsx index 9ffc884c1d151..8795ba7590217 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/nav_link.tsx +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/nav_link.tsx @@ -94,7 +94,7 @@ export function createEuiButtonItem({ navigateToUrl(url); }, isDisabled: disabled, - dataTestSubj: `collapsibleNavAppButton-${id}`, + 'data-test-subj': dataTestSubj || `collapsibleNavAppButton-${id}`, }; } diff --git a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx index 4719ccc92cd8d..c2561191deb9a 100644 --- a/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx +++ b/src/plugins/chart_expressions/expression_xy/public/expression_renderers/xy_chart_renderer.tsx @@ -278,7 +278,7 @@ export const getXyChartRenderer = ({ uiState={handlers.uiState as PersistedState} renderComplete={renderComplete} /> - {' '} +
, domNode diff --git a/src/plugins/home/public/application/components/tutorial_directory.js b/src/plugins/home/public/application/components/tutorial_directory.js index 6dc25ea63d7e0..cde8b86f5df22 100644 --- a/src/plugins/home/public/application/components/tutorial_directory.js +++ b/src/plugins/home/public/application/components/tutorial_directory.js @@ -69,12 +69,7 @@ class TutorialDirectoryUi extends React.Component { async componentDidMount() { this._isMounted = true; - getServices().chrome.setBreadcrumbs([ - { - text: integrationsTitle, - href: this.props.addBasePath(`/app/integrations/browse`), - }, - ]); + this.setBreadcrumbs(); const tutorialConfigs = await getTutorials(); @@ -135,6 +130,30 @@ class TutorialDirectoryUi extends React.Component { }); } + componentDidUpdate(prevProps, prevState) { + if (prevState.selectedTabId !== this.state.selectedTabId) { + this.setBreadcrumbs(); + } + } + + setBreadcrumbs = () => { + const tab = this.getSelectedTab(); + const breadcrumbs = [ + { + text: integrationsTitle, + href: this.props.addBasePath(`/app/integrations/browse`), + }, + ]; + + if (tab?.name) { + breadcrumbs.push({ + text: tab.name, + }); + } + + getServices().chrome.setBreadcrumbs(breadcrumbs); + }; + onSelectedTabChanged = (id) => { this.setState({ selectedTabId: id, @@ -150,18 +169,14 @@ class TutorialDirectoryUi extends React.Component { })); }; + getSelectedTab = () => { + return this.tabs.find(({ id }) => id === this.state.selectedTabId); + }; + renderTabContent = () => { - const tab = this.tabs.find(({ id }) => id === this.state.selectedTabId); + const tab = this.getSelectedTab(); + if (tab?.content) { - getServices().chrome.setBreadcrumbs([ - { - text: integrationsTitle, - href: this.props.addBasePath(`/app/integrations/browse`), - }, - { - text: tab.name, - }, - ]); return tab.content; } From 41b969ca3f9ceeed5b522a157899934a6822539c Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Thu, 9 Feb 2023 10:31:49 -0500 Subject: [PATCH 033/203] [Synthetics] alert config read only (#150491) ## Summary Relates to https://github.com/elastic/kibana/issues/150417 Resolves https://github.com/elastic/kibana/issues/150472 Adds alert config to ICMP monitors. Also allows alert config to be specified for project monitors. Screen Shot 2023-02-07 at 2 10 36 PM Screen Shot 2023-02-07 at 4 04 30 PM ## Testing 1. Navigate to Add/Monitor and click on ICMP monitor 2. Ensure the alert toggle appears and is able to be interacted with 3. Testing for project monitor alert config will have to be done after https://github.com/elastic/kibana/issues/150417, but api integration tests have been added. --------- Co-authored-by: shahzad31 --- .../project_monitor_read_only.journey.ts | 9 +- .../synthetics/services/get_monitor.ts | 7 +- .../monitor_add_edit/form/field_config.tsx | 6 +- .../monitor_add_edit/form/form_config.tsx | 1 + .../monitor_add_edit/form/formatter.test.tsx | 29 +++- .../monitor_add_edit/form/formatter.ts | 4 +- .../normalizers/common_fields.test.ts | 134 +++++++++++++++++- .../normalizers/common_fields.ts | 13 ++ .../apis/synthetics/add_monitor_project.ts | 37 +++++ 9 files changed, 232 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/project_monitor_read_only.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/project_monitor_read_only.journey.ts index 5daf18f855903..404f593bbdaa9 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/project_monitor_read_only.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/project_monitor_read_only.journey.ts @@ -11,12 +11,13 @@ import { cleanTestMonitors, enableMonitorManagedViaApi } from './services/add_mo import { getMonitor } from './services/get_monitor'; import { addTestMonitorProject } from './services/add_monitor_project'; import { syntheticsAppPageProvider } from '../../page_objects/synthetics/synthetics_app'; +import { SyntheticsMonitor } from '../../../common/runtime_types'; journey('Project Monitor Read-only', async ({ page, params }) => { recordVideo(page); const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); - let originalMonitorConfiguration: Record | undefined; + let originalMonitorConfiguration: SyntheticsMonitor | null; let monitorId: string; const monitorName = 'test-project-monitor'; @@ -70,6 +71,7 @@ journey('Project Monitor Read-only', async ({ page, params }) => { step('monitor can be enabled or disabled', async () => { await page.click('[data-test-subj="syntheticsEnableSwitch"]'); + await page.click('[data-test-subj="syntheticsAlertStatusSwitch"]'); await syntheticsApp.confirmAndSave(true); const newConfiguration = await getMonitor(params.kibanaUrl, monitorId); @@ -81,6 +83,11 @@ journey('Project Monitor Read-only', async ({ page, params }) => { ...originalMonitorConfiguration, hash: '', revision: 3, + alert: { + status: { + enabled: !(originalMonitorConfiguration?.alert?.status?.enabled as boolean), + }, + }, enabled: !originalMonitorConfiguration?.enabled, }); }); diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/services/get_monitor.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/services/get_monitor.ts index 20bd20ad10147..d23bc9971b9e0 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/services/get_monitor.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/services/get_monitor.ts @@ -6,8 +6,12 @@ */ import axios from 'axios'; +import { SyntheticsMonitor } from '../../../../common/runtime_types'; -export const getMonitor = async (kibanaUrl: string, monitorId: string) => { +export const getMonitor = async ( + kibanaUrl: string, + monitorId: string +): Promise => { try { const response = await axios.get(kibanaUrl + `/internal/uptime/service/monitors/${monitorId}`, { auth: { username: 'elastic', password: 'changeme' }, @@ -17,5 +21,6 @@ export const getMonitor = async (kibanaUrl: string, monitorId: string) => { } catch (e) { // eslint-disable-next-line no-console console.log(e); + return null; } }; 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 6cb68ae27cd7c..39e20a94000d4 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 @@ -443,6 +443,8 @@ export const FIELD = (readOnly?: boolean): FieldMap => ({ setValue(ConfigKey.ENABLED, !!event.target.checked); }, 'data-test-subj': 'syntheticsEnableSwitch', + // enabled is an allowed field for read only + // isDisabled: readOnly, }), }, [AlertConfigKey.STATUS_ENABLED]: { @@ -465,7 +467,9 @@ export const FIELD = (readOnly?: boolean): FieldMap => ({ onChange: (event) => { setValue(AlertConfigKey.STATUS_ENABLED, !!event.target.checked); }, - disabled: readOnly, + 'data-test-subj': 'syntheticsAlertStatusSwitch', + // alert config is an allowed field for read only + // isDisabled: readOnly, }), }, [ConfigKey.TAGS]: { 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 f4a099eaa76db..a33f0e14b7777 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 @@ -263,6 +263,7 @@ export const FORM_CONFIG = (readOnly: boolean): FieldConfig => ({ FIELD(readOnly)[ConfigKey.WAIT], FIELD(readOnly)[ConfigKey.TIMEOUT], FIELD(readOnly)[ConfigKey.ENABLED], + FIELD(readOnly)[AlertConfigKey.STATUS_ENABLED], ], advanced: [DEFAULT_DATA_OPTIONS(readOnly)], }, 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 a534438b7df0d..6a457d601802b 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 @@ -5,7 +5,7 @@ * 2.0. */ -import { format, READ_ONLY_FIELDS } from './formatter'; +import { format, ALLOWED_FIELDS } from './formatter'; import { DataStream } from '../../../../../../common/runtime_types'; import { DEFAULT_FIELDS } from '../../../../../../common/constants/monitor_defaults'; @@ -84,6 +84,11 @@ describe('format', () => { include_headers: true, include_body: 'on_error', }, + alert: { + status: { + enabled: false, + }, + }, }; }); @@ -140,6 +145,11 @@ describe('format', () => { 'url.port': null, username: '', id: '', + alert: { + status: { + enabled: false, + }, + }, }); }); @@ -224,6 +234,11 @@ describe('format', () => { service: { name: '', }, + alert: { + status: { + enabled: false, + }, + }, }; expect(format(browserFormFields)).toEqual({ ...DEFAULT_FIELDS[DataStream.BROWSER], @@ -290,6 +305,11 @@ describe('format', () => { 'url.port': null, urls: '', id: '', + alert: { + status: { + enabled: false, + }, + }, }); } ); @@ -356,12 +376,17 @@ describe('format', () => { 'url.port': null, username: '', id: '', + alert: { + status: { + enabled: false, + }, + }, }); }); it('handles read only', () => { expect(format(formValues, true)).toEqual( - READ_ONLY_FIELDS.reduce>((acc, key) => { + ALLOWED_FIELDS.reduce>((acc, key) => { acc[key] = formValues[key]; return acc; }, {}) 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 1ce3d1258e5fa..e7a42d067533a 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 @@ -20,7 +20,7 @@ export const formatter = (fields: Record) => { return monitorFields as MonitorFields; }; -export const READ_ONLY_FIELDS = [ConfigKey.ENABLED]; +export const ALLOWED_FIELDS = [ConfigKey.ENABLED, ConfigKey.ALERT_CONFIG]; export const format = (fields: Record, readOnly: boolean = false) => { const formattedFields = formatter(fields) as MonitorFields; @@ -65,5 +65,5 @@ export const format = (fields: Record, readOnly: boolean = fals }, }; const formFields = formattedMap[fields[ConfigKey.FORM_MONITOR_TYPE] as FormMonitorType]; - return readOnly ? pick(formFields, READ_ONLY_FIELDS) : formFields; + return readOnly ? pick(formFields, ALLOWED_FIELDS) : formFields; }; diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts index fee6f0ca2637c..a05382b0a5ebf 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.test.ts @@ -5,7 +5,11 @@ * 2.0. */ -import { flattenAndFormatObject } from './common_fields'; +import { + flattenAndFormatObject, + getNormalizeCommonFields, + NormalizedProjectProps, +} from './common_fields'; describe('normalizeYamlConfig', () => { it('does not continue flattening when encountering an array', () => { @@ -64,3 +68,131 @@ describe('normalizeYamlConfig', () => { }); }); }); + +describe('getNormalizeCommonFields', () => { + it.each([true, false, undefined, null])( + 'handles configuring monitor alert config when defined', + (statusEnabled) => { + const locations = [ + { + label: 'US North America', + id: 'us_central', + isServiceManaged: true, + }, + ]; + const config = { + locations, + privateLocations: [], + projectId: 'test-projectId', + monitor: { + name: 'A monitor', + id: 'test-id', + type: 'http', + urls: 'https://elastic.co', + locations: ['us_central'], + schedule: 3, + alert: { + status: { + enabled: statusEnabled, + }, + }, + }, + namespace: 'test-namespace', + version: '8.7.0', + }; + const normalizedFields = getNormalizeCommonFields(config as NormalizedProjectProps); // typecasting to allow testing of invalid user configs + expect(normalizedFields).toEqual({ + errors: [], + normalizedFields: { + alert: { + status: { + enabled: statusEnabled ?? true, + }, + }, + custom_heartbeat_id: 'test-id-test-projectId-test-namespace', + enabled: true, + hash: '', + journey_id: 'test-id', + locations: [ + { + geo: undefined, + id: 'us_central', + isServiceManaged: true, + label: 'US North America', + }, + ], + name: 'A monitor', + namespace: 'test_namespace', + origin: 'project', + original_space: 'test-namespace', + project_id: 'test-projectId', + schedule: { + number: '3', + unit: 'm', + }, + tags: [], + timeout: '16', + }, + }); + } + ); + + it('handles configuring monitor alert config when alert config is not defined', () => { + const locations = [ + { + label: 'US North America', + id: 'us_central', + isServiceManaged: true, + }, + ]; + const config = { + locations, + privateLocations: [], + projectId: 'test-projectId', + monitor: { + name: 'A monitor', + id: 'test-id', + type: 'http', + urls: 'https://elastic.co', + locations: ['us_central'], + schedule: 3, + }, + namespace: 'test-namespace', + version: '8.7.0', + }; + const normalizedFields = getNormalizeCommonFields(config as NormalizedProjectProps); // typecasting to allow testing of invalid user configs + expect(normalizedFields).toEqual({ + errors: [], + normalizedFields: { + alert: { + status: { + enabled: true, + }, + }, + custom_heartbeat_id: 'test-id-test-projectId-test-namespace', + enabled: true, + hash: '', + journey_id: 'test-id', + locations: [ + { + geo: undefined, + id: 'us_central', + isServiceManaged: true, + label: 'US North America', + }, + ], + name: 'A monitor', + namespace: 'test_namespace', + origin: 'project', + original_space: 'test-namespace', + project_id: 'test-projectId', + schedule: { + number: '3', + unit: 'm', + }, + tags: [], + timeout: '16', + }, + }); + }); +}); diff --git a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts index e84990f5ac43a..d134ed069bee0 100644 --- a/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts +++ b/x-pack/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts @@ -84,6 +84,19 @@ export const getNormalizeCommonFields = ({ ? getValueInSeconds(monitor.timeout) : defaultFields[ConfigKey.TIMEOUT], [ConfigKey.CONFIG_HASH]: monitor.hash || defaultFields[ConfigKey.CONFIG_HASH], + // picking out keys specifically, so users can't add arbitrary fields + [ConfigKey.ALERT_CONFIG]: monitor.alert + ? { + ...defaultFields[ConfigKey.ALERT_CONFIG], + status: { + ...defaultFields[ConfigKey.ALERT_CONFIG]?.status, + enabled: + monitor.alert?.status?.enabled ?? + defaultFields[ConfigKey.ALERT_CONFIG]?.status?.enabled ?? + true, + }, + } + : defaultFields[ConfigKey.ALERT_CONFIG], }; return { normalizedFields, errors }; }; diff --git a/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts b/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts index ba98b589f83b1..4bc005c46596c 100644 --- a/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts +++ b/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts @@ -1815,5 +1815,42 @@ export default function ({ getService }: FtrProviderContext) { ]); } }); + + it('project monitors - handles alert config without adding arbitrary fields', async () => { + const project = `test-project-${uuidv4()}`; + const testAlert = { + status: { enabled: false, doesnotexit: true }, + }; + try { + await supertest + .put(`${API_URLS.SYNTHETICS_MONITORS_PROJECT_UPDATE.replace('{projectName}', project)}`) + .set('kbn-xsrf', 'true') + .send({ + monitors: [ + { + ...httpProjectMonitors.monitors[1], + alert: testAlert, + }, + ], + }) + .expect(200); + const getResponse = await supertest + .get(`${API_URLS.SYNTHETICS_MONITORS}`) + .query({ + filter: `${syntheticsMonitorType}.attributes.journey_id: ${httpProjectMonitors.monitors[1].id}`, + }) + .set('kbn-xsrf', 'true') + .expect(200); + const { monitors } = getResponse.body; + expect(monitors.length).eql(1); + expect(monitors[0].attributes[ConfigKey.ALERT_CONFIG]).eql({ + status: { + enabled: testAlert.status.enabled, + }, + }); + } finally { + await deleteMonitor(httpProjectMonitors.monitors[1].id, project); + } + }); }); } From 3b6ae1c0393692dcbde4e0065a64adc4c0783415 Mon Sep 17 00:00:00 2001 From: Elena Stoeva <59341489+ElenaStoeva@users.noreply.github.com> Date: Thu, 9 Feb 2023 15:39:19 +0000 Subject: [PATCH 034/203] Add _meta field to Ingest pipelines form (#149976) Closes https://github.com/elastic/kibana/issues/108289 ## Summary This PR adds support for the `_meta` field in the Ingest Pipelines form. Recording: https://user-images.githubusercontent.com/59341489/217812239-a8e0ebc7-5c91-495f-8f86-9f16a563cab2.mov ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../helpers/pipeline_form.helpers.ts | 14 ++++ .../ingest_pipelines_create.test.tsx | 31 ++++++- .../plugins/ingest_pipelines/common/types.ts | 1 + .../pipeline_form/pipeline_form.tsx | 2 + .../pipeline_form/pipeline_form_fields.tsx | 52 +++++++++++- .../components/pipeline_form/schema.ts | 45 ----------- .../components/pipeline_form/schema.tsx | 80 +++++++++++++++++++ .../public/application/lib/utils.test.ts | 56 ++++++++++--- .../public/application/lib/utils.ts | 15 ++-- .../pipelines_list/details_flyout.tsx | 17 ++++ .../server/routes/api/create.ts | 3 +- .../routes/api/shared/pipeline_schema.ts | 1 + .../server/routes/api/update.ts | 3 +- .../ingest_pipelines/ingest_pipelines.ts | 35 +++++++- 14 files changed, 287 insertions(+), 68 deletions(-) delete mode 100644 x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.ts create mode 100644 x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts index 775d05a865189..b4014eca85775 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/helpers/pipeline_form.helpers.ts @@ -37,10 +37,22 @@ export const getFormActions = (testBed: TestBed) => { component.update(); }; + const toggleMetaSwitch = () => { + act(() => { + form.toggleEuiSwitch('metaToggle'); + }); + }; + + const setMetaField = (value: object) => { + find('metaEditor').simulate('change', { jsonString: JSON.stringify(value) }); + }; + return { clickSubmitButton, clickShowRequestLink, toggleVersionSwitch, + toggleMetaSwitch, + setMetaField, }; }; @@ -54,6 +66,8 @@ export type PipelineFormTestSubjects = | 'pipelineForm' | 'versionToggle' | 'versionField' + | 'metaToggle' + | 'metaEditor' | 'nameField.input' | 'descriptionField.input' | 'processorsEditor' diff --git a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx index f67d9d24ed690..fe371138487e8 100644 --- a/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx +++ b/x-pack/plugins/ingest_pipelines/__jest__/client_integration/ingest_pipelines_create.test.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { act } from 'react-dom/test-utils'; +import '@kbn/es-ui-shared-plugin/public/components/code_editor/jest_mock'; import { setupEnvironment, pageHelpers } from './helpers'; import { API_BASE_PATH } from '../../common/constants'; import { PipelinesCreateTestBed } from './helpers/pipelines_create.helpers'; @@ -70,6 +71,21 @@ describe('', () => { expect(exists('versionField')).toBe(true); }); + test('should toggle the _meta field', async () => { + const { exists, component, actions } = testBed; + + // Meta editor should be hidden by default + expect(exists('metaEditor')).toBe(false); + + await act(async () => { + actions.toggleMetaSwitch(); + }); + + component.update(); + + expect(exists('metaEditor')).toBe(true); + }); + test('should show the request flyout', async () => { const { actions, find, exists } = testBed; @@ -134,7 +150,19 @@ describe('', () => { }); test('should send the correct payload', async () => { - const { actions } = testBed; + const { component, actions } = testBed; + + await act(async () => { + actions.toggleMetaSwitch(); + }); + component.update(); + const metaData = { + field1: 'hello', + field2: 10, + }; + await act(async () => { + actions.setMetaField(metaData); + }); await actions.clickSubmitButton(); @@ -144,6 +172,7 @@ describe('', () => { body: JSON.stringify({ name: 'my_pipeline', description: 'pipeline description', + _meta: metaData, processors: [], }), }) diff --git a/x-pack/plugins/ingest_pipelines/common/types.ts b/x-pack/plugins/ingest_pipelines/common/types.ts index 2419d2b7975f0..69c4b6c52b4b8 100644 --- a/x-pack/plugins/ingest_pipelines/common/types.ts +++ b/x-pack/plugins/ingest_pipelines/common/types.ts @@ -22,6 +22,7 @@ export interface Pipeline { description?: string; version?: number; processors: Processor[]; + _meta?: { [key: string]: any }; on_failure?: Processor[]; isManaged?: boolean; } diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx index ebb177f504c70..65e19b2178baf 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form.tsx @@ -36,6 +36,7 @@ const defaultFormValue: Pipeline = Object.freeze({ description: '', processors: [], on_failure: [], + _meta: {}, }); export const PipelineForm: React.FunctionComponent = ({ @@ -131,6 +132,7 @@ export const PipelineForm: React.FunctionComponent = ({ onFailure={processorsState.onFailure} onProcessorsUpdate={onProcessorsChangeHandler} hasVersion={Boolean(defaultValue.version)} + hasMeta={Boolean(defaultValue._meta && Object.keys(defaultValue._meta).length)} isEditing={isEditing} canEditName={canEditName} /> diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx index aac3fa2914467..ce9a05f666be0 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/pipeline_form_fields.tsx @@ -9,9 +9,10 @@ import React, { useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiSpacer, EuiSwitch } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { Processor } from '../../../../common/types'; -import { getUseField, getFormRow, Field } from '../../../shared_imports'; +import { getUseField, getFormRow, Field, JsonEditorField } from '../../../shared_imports'; import { ProcessorsEditorContextProvider, @@ -26,6 +27,7 @@ interface Props { onLoadJson: OnDoneLoadJsonHandler; onProcessorsUpdate: OnUpdateHandler; hasVersion: boolean; + hasMeta: boolean; onEditorFlyoutOpen: () => void; isEditing?: boolean; canEditName?: boolean; @@ -41,11 +43,14 @@ export const PipelineFormFields: React.FunctionComponent = ({ onProcessorsUpdate, isEditing, hasVersion, + hasMeta, onEditorFlyoutOpen, canEditName, }) => { const [isVersionVisible, setIsVersionVisible] = useState(hasVersion); + const [isMetaVisible, setIsMetaVisible] = useState(hasMeta); + return ( <> {/* Name field with optional version field */} @@ -124,6 +129,51 @@ export const PipelineFormFields: React.FunctionComponent = ({ > + + {/* _meta field */} + + } + description={ + <> + + + + + + } + checked={isMetaVisible} + onChange={(e) => setIsMetaVisible(e.target.checked)} + data-test-subj="metaToggle" + /> + + } + > + {isMetaVisible && ( + + )} + ); }; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.ts deleted file mode 100644 index a51779456786f..0000000000000 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.ts +++ /dev/null @@ -1,45 +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'; -import { FormSchema, FIELD_TYPES, fieldValidators, fieldFormatters } from '../../../shared_imports'; - -import { PipelineForm } from './types'; - -const { emptyField } = fieldValidators; -const { toInt } = fieldFormatters; - -export const pipelineFormSchema: FormSchema = { - name: { - type: FIELD_TYPES.TEXT, - label: i18n.translate('xpack.ingestPipelines.form.nameFieldLabel', { - defaultMessage: 'Name', - }), - validations: [ - { - validator: emptyField( - i18n.translate('xpack.ingestPipelines.form.pipelineNameRequiredError', { - defaultMessage: 'Name is required.', - }) - ), - }, - ], - }, - description: { - type: FIELD_TYPES.TEXTAREA, - label: i18n.translate('xpack.ingestPipelines.form.descriptionFieldLabel', { - defaultMessage: 'Description (optional)', - }), - }, - version: { - type: FIELD_TYPES.NUMBER, - label: i18n.translate('xpack.ingestPipelines.form.versionFieldLabel', { - defaultMessage: 'Version (optional)', - }), - formatters: [toInt], - }, -}; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx new file mode 100644 index 0000000000000..41635b9767da2 --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_form/schema.tsx @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { FormattedMessage } from '@kbn/i18n-react'; +import { EuiCode } from '@elastic/eui'; +import React from 'react'; +import { parseJson, stringifyJson } from '../../lib/utils'; +import { FormSchema, FIELD_TYPES, fieldValidators, fieldFormatters } from '../../../shared_imports'; + +const { emptyField, isJsonField } = fieldValidators; +const { toInt } = fieldFormatters; + +export const pipelineFormSchema: FormSchema = { + name: { + type: FIELD_TYPES.TEXT, + label: i18n.translate('xpack.ingestPipelines.form.nameFieldLabel', { + defaultMessage: 'Name', + }), + validations: [ + { + validator: emptyField( + i18n.translate('xpack.ingestPipelines.form.pipelineNameRequiredError', { + defaultMessage: 'Name is required.', + }) + ), + }, + ], + }, + description: { + type: FIELD_TYPES.TEXTAREA, + label: i18n.translate('xpack.ingestPipelines.form.descriptionFieldLabel', { + defaultMessage: 'Description (optional)', + }), + }, + version: { + type: FIELD_TYPES.NUMBER, + label: i18n.translate('xpack.ingestPipelines.form.versionFieldLabel', { + defaultMessage: 'Version (optional)', + }), + formatters: [toInt], + }, + _meta: { + label: i18n.translate('xpack.ingestPipelines.form.metaFieldLabel', { + defaultMessage: '_meta field data (optional)', + }), + helpText: ( + {JSON.stringify({ arbitrary_data: 'anything_goes' })}, + }} + /> + ), + serializer: (value) => { + const result = parseJson(value, false); + // If an empty object was passed, strip out this value entirely. + if (!Object.keys(result).length) { + return undefined; + } + return result; + }, + deserializer: (value) => stringifyJson(value, false), + validations: [ + { + validator: isJsonField( + i18n.translate('xpack.ingestPipelines.form.validation.metaJsonError', { + defaultMessage: 'The input is not valid.', + }), + { allowEmptyString: true } + ), + }, + ], + }, +}; diff --git a/x-pack/plugins/ingest_pipelines/public/application/lib/utils.test.ts b/x-pack/plugins/ingest_pipelines/public/application/lib/utils.test.ts index 9005e7e5cfd63..7a7290b3f1de4 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/lib/utils.test.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/lib/utils.test.ts @@ -9,31 +9,63 @@ import { stringifyJson, parseJson } from './utils'; describe('utils', () => { describe('stringifyJson()', () => { - it('should stringify a valid JSON array', () => { - expect(stringifyJson([1, 2, 3])).toEqual(`[ + describe('when rendering as an array', () => { + it('should stringify a valid JSON array', () => { + expect(stringifyJson([1, 2, 3])).toEqual(`[ 1, 2, 3 ]`); + }); + + it('should return a stringified empty array if the value is not a valid JSON array', () => { + expect(stringifyJson({})).toEqual('[\n\n]'); + }); }); - it('should return a stringified empty array if the value is not a valid JSON array', () => { - expect(stringifyJson({})).toEqual('[\n\n]'); + describe('when rendering as an object', () => { + it('should stringify a valid JSON object', () => { + expect(stringifyJson({ field_1: 'hello', field_2: 5, field_3: true }, false)).toEqual(`{ + "field_1": "hello", + "field_2": 5, + "field_3": true +}`); + }); + + it('should return a stringified empty object if the value is not a valid JSON object', () => { + expect(stringifyJson([1, 2, 3], false)).toEqual('{\n\n}'); + expect(stringifyJson('test', false)).toEqual('{\n\n}'); + expect(stringifyJson(10, false)).toEqual('{\n\n}'); + }); }); }); describe('parseJson()', () => { - it('should parse a valid JSON string', () => { - expect(parseJson('[1,2,3]')).toEqual([1, 2, 3]); - expect(parseJson('[{"foo": "bar"}]')).toEqual([{ foo: 'bar' }]); - }); + describe('when rendering as an array', () => { + it('should parse a valid JSON string', () => { + expect(parseJson('[1,2,3]')).toEqual([1, 2, 3]); + expect(parseJson('[{"foo": "bar"}]')).toEqual([{ foo: 'bar' }]); + }); - it('should convert valid JSON that is not an array to an array', () => { - expect(parseJson('{"foo": "bar"}')).toEqual([{ foo: 'bar' }]); + it('should convert valid JSON that is not an array to an array', () => { + expect(parseJson('{"foo": "bar"}')).toEqual([{ foo: 'bar' }]); + }); + + it('should return an empty array if invalid JSON string', () => { + expect(parseJson('{invalidJsonString}')).toEqual([]); + }); }); - it('should return an empty array if invalid JSON string', () => { - expect(parseJson('{invalidJsonString}')).toEqual([]); + describe('when rendering as an object', () => { + it('should parse a valid JSON string', () => { + expect(parseJson('{"foo": "bar"}', false)).toEqual({ foo: 'bar' }); + expect(parseJson('{}', false)).toEqual({}); + }); + + it('should return an empty object if invalid JSON string', () => { + expect(parseJson('{invalidJsonString}', false)).toEqual({}); + expect(parseJson('[invalidJsonString]', false)).toEqual({}); + }); }); }); }); diff --git a/x-pack/plugins/ingest_pipelines/public/application/lib/utils.ts b/x-pack/plugins/ingest_pipelines/public/application/lib/utils.ts index d3eb5233e87c1..c789bc013a9ff 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/lib/utils.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/lib/utils.ts @@ -5,21 +5,26 @@ * 2.0. */ -export const stringifyJson = (json: any): string => - Array.isArray(json) ? JSON.stringify(json, null, 2) : '[\n\n]'; +export const stringifyJson = (json: any, renderAsArray: boolean = true): string => + (renderAsArray && Array.isArray(json)) || + (!renderAsArray && json && typeof json === 'object' && !Array.isArray(json)) + ? JSON.stringify(json, null, 2) + : renderAsArray + ? '[\n\n]' + : '{\n\n}'; -export const parseJson = (jsonString: string): object[] => { +export const parseJson = (jsonString: string, renderAsArray: boolean = true): object[] => { let parsedJSON: any; try { parsedJSON = JSON.parse(jsonString); - if (!Array.isArray(parsedJSON)) { + if (renderAsArray && !Array.isArray(parsedJSON)) { // Convert object to array parsedJSON = [parsedJSON]; } } catch { - parsedJSON = []; + parsedJSON = renderAsArray ? [] : {}; } return parsedJSON; diff --git a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx index 98db398f486cf..9723a264a565d 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/sections/pipelines_list/details_flyout.tsx @@ -25,11 +25,13 @@ import { EuiContextMenu, EuiButton, EuiBadge, + EuiCodeBlock, } from '@elastic/eui'; import { Pipeline } from '../../../../common/types'; import { PipelineDetailsJsonBlock } from './details_json_block'; +import { stringifyJson } from '../../lib/utils'; export interface Props { pipeline: Pipeline; @@ -186,6 +188,21 @@ export const PipelineDetailsFlyout: FunctionComponent = ({ )} + + {/* Metadata (optional) */} + {pipeline._meta && ( + <> + + + + + {stringifyJson(pipeline._meta, false)} + + + )} diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts index 1e59151f73885..4ec2d54b0280f 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/create.ts @@ -34,7 +34,7 @@ export const registerCreateRoute = ({ const pipeline = req.body as Pipeline; // eslint-disable-next-line @typescript-eslint/naming-convention - const { name, description, processors, version, on_failure } = pipeline; + const { name, description, processors, version, on_failure, _meta } = pipeline; try { // Check that a pipeline with the same name doesn't already exist @@ -66,6 +66,7 @@ export const registerCreateRoute = ({ processors, version, on_failure, + _meta, }, }); diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/shared/pipeline_schema.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/shared/pipeline_schema.ts index c33dc50d39af2..d5a7f4221647f 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/shared/pipeline_schema.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/shared/pipeline_schema.ts @@ -12,4 +12,5 @@ export const pipelineSchema = { processors: schema.arrayOf(schema.recordOf(schema.string(), schema.any())), version: schema.maybe(schema.number()), on_failure: schema.maybe(schema.arrayOf(schema.recordOf(schema.string(), schema.any()))), + _meta: schema.maybe(schema.object({}, { unknowns: 'allow' })), }; diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts index 5b1b032c8aedb..3ed888e254009 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/update.ts @@ -33,7 +33,7 @@ export const registerUpdateRoute = ({ const { client: clusterClient } = (await ctx.core).elasticsearch; const { name } = req.params; // eslint-disable-next-line @typescript-eslint/naming-convention - const { description, processors, version, on_failure } = req.body; + const { description, processors, version, on_failure, _meta } = req.body; try { // Verify pipeline exists; ES will throw 404 if it doesn't @@ -46,6 +46,7 @@ export const registerUpdateRoute = ({ processors, version, on_failure, + _meta, }, }); diff --git a/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts b/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts index 46b11174d8ede..3c044250b00bf 100644 --- a/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts +++ b/x-pack/test/api_integration/apis/management/ingest_pipelines/ingest_pipelines.ts @@ -61,6 +61,10 @@ export default function ({ getService }: FtrProviderContext) { }, ], version: 1, + _meta: { + field_1: 'test', + field_2: 10, + }, }) .expect(200); @@ -73,7 +77,7 @@ export default function ({ getService }: FtrProviderContext) { const { body } = await supertest .post(API_BASE_PATH) .set('kbn-xsrf', 'xxx') - // Excludes description, version and on_failure processors + // Excludes description, version, on_failure processors, and _meta .send({ name: REQUIRED_FIELDS_PIPELINE_ID, processors: [ @@ -106,6 +110,10 @@ export default function ({ getService }: FtrProviderContext) { }, ], version: 1, + _meta: { + field_1: 'test', + field_2: 10, + }, }) .expect(409); @@ -137,6 +145,10 @@ export default function ({ getService }: FtrProviderContext) { }, }, ], + _meta: { + field_1: 'test', + field_2: 10, + }, }; before(async () => { @@ -159,6 +171,10 @@ export default function ({ getService }: FtrProviderContext) { .send({ ...PIPELINE, description: 'updated test pipeline description', + _meta: { + field_1: 'updated', + new_field: 3, + }, }) .expect(200); @@ -175,7 +191,7 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .send({ processors: PIPELINE.processors, - // removes description, version and on_failure + // removes description, version, on_failure, and _meta }) .expect(200); @@ -193,6 +209,10 @@ export default function ({ getService }: FtrProviderContext) { .send({ ...PIPELINE, description: 'updated test pipeline description', + _meta: { + field_1: 'updated', + new_field: 3, + }, }) .expect(404); @@ -217,6 +237,10 @@ export default function ({ getService }: FtrProviderContext) { }, ], version: 1, + _meta: { + field_1: 'test', + field_2: 10, + }, }; before(async () => { @@ -274,6 +298,10 @@ export default function ({ getService }: FtrProviderContext) { }, ], version: 1, + _meta: { + field_1: 'test', + field_2: 10, + }, }; const pipelineA = { body: PIPELINE, id: 'test_delete_pipeline_a' }; @@ -378,6 +406,9 @@ export default function ({ getService }: FtrProviderContext) { }, }, ], + _meta: { + field: 'test simulate metadata', + }, }, documents: [ { From d0b0985ebe43c4a598a6f11ae1de70cba6294d17 Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Thu, 9 Feb 2023 10:50:11 -0500 Subject: [PATCH 035/203] [Fleet] Fix Fleet OpenAPI errors (#150583) ## Summary Fixes https://github.com/elastic/kibana/issues/149990 There's still plenty of warnings to clean up, and I think we should file a separate issue to follow up on them. Missing descriptions, empty tags, etc are things we can certainly clean up ahead of the API being labeled as GA, they'll just be a little time consuming to track down. The goal of this PR is simply to remove the `error` level output from the linters as specified in the linked issue. ## To test I've added some convenience scripts in `x-pack/plugins/fleet/package.json` to make working with the OpenAPI spec easier. You can view the lint output of the built `bundled.yaml` or `bundled.json` file by running the following: ``` $ # From Kibana root $ cd x-pack/plugins/fleet # Runs redocly linter $ yarn openapi:lint # Runs speccy $ yarn openapi:speccy ``` If you need to rebuild the `bundled` spec files, there's a script now as well: ``` $ yarn openapi:build ``` Redocly reports 89 warnings and no errors, which should suffice in resolving the linked issue. cc @lcawl Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/fleet/common/openapi/bundled.json | 16 ++++++++++++++-- x-pack/plugins/fleet/common/openapi/bundled.yaml | 8 ++++++++ .../openapi/components/headers/kbn_xsrf.yaml | 1 + .../common/openapi/paths/agent_status@data.yaml | 2 ++ ...ts@{agent_id}@actions@{action_id}@cancel.yaml | 5 +++++ x-pack/plugins/fleet/package.json | 5 ++++- 6 files changed, 34 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 9c4609e76adac..c4082843e25c9 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -1304,7 +1304,10 @@ "parameters": [ { "schema": { - "type": "array" + "type": "array", + "items": { + "type": "string" + } }, "name": "agentsIds", "in": "query", @@ -1719,6 +1722,14 @@ }, "/agents/{agentId}/actions/{actionId}/cancel": { "parameters": [ + { + "schema": { + "type": "string" + }, + "name": "agentId", + "in": "path", + "required": true + }, { "schema": { "type": "string" @@ -4602,7 +4613,8 @@ }, "in": "header", "name": "kbn-xsrf", - "required": true + "required": true, + "description": "Kibana's anti Cross-Site Request Forgery token. Can be any string value." }, "page_size": { "name": "perPage", diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 74440cfaf2d4f..654918ddc265d 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -822,6 +822,8 @@ paths: parameters: - schema: type: array + items: + type: string name: agentsIds in: query required: true @@ -1071,6 +1073,11 @@ paths: $ref: '#/components/schemas/agent_action' /agents/{agentId}/actions/{actionId}/cancel: parameters: + - schema: + type: string + name: agentId + in: path + required: true - schema: type: string name: actionId @@ -2858,6 +2865,7 @@ components: in: header name: kbn-xsrf required: true + description: Kibana's anti Cross-Site Request Forgery token. Can be any string value. page_size: name: perPage in: query diff --git a/x-pack/plugins/fleet/common/openapi/components/headers/kbn_xsrf.yaml b/x-pack/plugins/fleet/common/openapi/components/headers/kbn_xsrf.yaml index 3d8dfae634e68..60cfcf67567aa 100644 --- a/x-pack/plugins/fleet/common/openapi/components/headers/kbn_xsrf.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/headers/kbn_xsrf.yaml @@ -3,3 +3,4 @@ schema: in: header name: kbn-xsrf required: true +description: Kibana's anti Cross-Site Request Forgery token. Can be any string value. diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml index 79eed1f24fe36..e1a758d55dce2 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_status@data.yaml @@ -22,6 +22,8 @@ get: parameters: - schema: type: array + items: + type: string name: agentsIds in: query required: true diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions@{action_id}@cancel.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions@{action_id}@cancel.yaml index 666abed1fce35..f17d6e4b25cf3 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions@{action_id}@cancel.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions@{action_id}@cancel.yaml @@ -1,4 +1,9 @@ parameters: + - schema: + type: string + name: agentId + in: path + required: true - schema: type: string name: actionId diff --git a/x-pack/plugins/fleet/package.json b/x-pack/plugins/fleet/package.json index fd76bcd2d2a6a..d7687fbac90dc 100644 --- a/x-pack/plugins/fleet/package.json +++ b/x-pack/plugins/fleet/package.json @@ -11,6 +11,9 @@ "cypress:run": "yarn cypress:run:reporter --browser chrome --spec './cypress/e2e/**/*.cy.ts'; status=$?; yarn junit:merge && exit $status", "cypress:run-as-ci": "node ../../../scripts/functional_tests --config ../../test/fleet_cypress/cli_config.ts", "cypress:run:reporter": "yarn cypress run --config-file ./cypress.config.ts --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json", - "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-fleet/cypress/results/mochawesome*.json > ../../../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/" + "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-fleet/cypress/results/mochawesome*.json > ../../../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/", + "openapi:build": "npx @redocly/openapi-cli bundle --ext yaml --output ./common/openapi/bundled.yaml ./common/openapi/entrypoint.yaml && npx @redocly/openapi-cli bundle --ext json --output ./common/openapi/bundled.json ./common/openapi/entrypoint.yaml", + "openapi:lint": "npx @redocly/cli lint ./common/openapi/bundled.yaml", + "openapi:speccy": "npx speccy lint ./common/openapi/bundled.yaml" } } From 430892919e303225d12a57238df292e9b0d0cd8f Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Thu, 9 Feb 2023 17:02:40 +0100 Subject: [PATCH 036/203] [Synthetics] Restrict user with limited Fleet permissions to manipulate monitors (#150402) Closes #137471 ## Summary Adds checks at various points (add, edit, delete, enable, disable actions) and asserts if user has the necessary Synthetics and Fleet (Integrations Read/Write) permissions. - A user with no `capabilities.uptime.save` permission won't be able to edit, delete, enable or disable a monitor on Overview, Management and Details page. - A user with no `fleet.authz.integrations.writeIntegrationPolicies` permission won't be able to create, update, enable or disable a monitor with at least one Private Location selected. - A user with no `fleet.authz.integrations.writeIntegrationPolicies` permission won't be able to create or delete a Private Location from Synthetics -> Settings. Action buttons and menu items will be disabled, with a tooltip conveying the reason why the button is disabled. ### Testing 1. Setup Kibana and Synthetics and so that you are able to create monitors with both public and private locations. 2. Create a few monitors using a user having both synthetics and fleet permissions. 3. Test different actions (create, edit, delete, enable, disable) with a user having no synthetics permissions. 3. Test different actions with a user having synthetics permissions but no fleet permissions. ![Screenshot 2023-02-07 at 02 25 53](https://user-images.githubusercontent.com/2748376/217142767-0b82abc2-656c-4f65-9dae-cddaaaac5688.png) ![Screenshot 2023-02-07 at 04 10 43](https://user-images.githubusercontent.com/2748376/217142783-6958836d-11cc-4e82-9879-fc4031f13567.png) v87 ![Screenshot 2023-02-07 at 04 13 06](https://user-images.githubusercontent.com/2748376/217142785-30bf45c8-1e19-4522-af8e-bed32f6948ba.png) ![Screenshot 2023-02-07 at 04 13 23](https://user-images.githubusercontent.com/2748376/217142793-c09a0273-1829-418a-9126-7da296c223ae.png) --------- Co-authored-by: shahzad31 Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/components/permissions.tsx | 109 ++++++++++++++++++ .../components/common/links/edit_monitor.tsx | 33 ------ .../getting_started/simple_monitor_form.tsx | 35 ++++-- .../monitor_add_edit/form/submit.tsx | 35 ++++-- .../monitor_summary/edit_monitor_link.tsx | 47 ++++++++ .../monitor_details/route_config.tsx | 2 +- .../monitor_details/run_test_manually.tsx | 18 ++- .../monitors_page/create_monitor_button.tsx | 43 ++++--- .../management/monitor_list_table/columns.tsx | 31 ++++- .../monitor_list_table/monitor_enabled.tsx | 37 +++--- .../overview/overview/actions_popover.tsx | 39 ++++++- .../private_locations/add_location_flyout.tsx | 14 +-- .../private_locations/delete_location.tsx | 23 ++-- .../private_locations/locations_table.tsx | 12 +- .../manage_private_locations.tsx | 20 ++-- .../private_locations/policy_name.tsx | 4 +- .../private_locations/translations.ts | 23 ---- .../public/apps/synthetics/hooks/index.ts | 2 + .../use_fleet_permissions.ts} | 30 ++++- 19 files changed, 391 insertions(+), 166 deletions(-) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/permissions.tsx delete mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/edit_monitor.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/edit_monitor_link.tsx delete mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/translations.ts rename x-pack/plugins/synthetics/public/apps/synthetics/{components/settings/private_locations/hooks/use_private_location_permission.ts => hooks/use_fleet_permissions.ts} (52%) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/permissions.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/permissions.tsx new file mode 100644 index 0000000000000..e9094bbc9a3f0 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/permissions.tsx @@ -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 React, { ReactNode } from 'react'; +import { EuiCallOut, EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +export const FleetPermissionsCallout = () => { + return ( + +

{NEED_FLEET_READ_AGENT_POLICIES_PERMISSION}

+
+ ); +}; + +/** + * If any of the canEditSynthetics or canUpdatePrivateMonitor is false, then wrap the children with a tooltip + * so that a reason can be conveyed to the user explaining why the action is disabled. + */ +export const NoPermissionsTooltip = ({ + canEditSynthetics = true, + canUpdatePrivateMonitor = true, + canAddPrivateMonitor = true, + children, +}: { + canEditSynthetics?: boolean; + canUpdatePrivateMonitor?: boolean; + canAddPrivateMonitor?: boolean; + children: ReactNode; +}) => { + const disabledMessage = getRestrictionReasonLabel( + canEditSynthetics, + canUpdatePrivateMonitor, + canAddPrivateMonitor + ); + if (disabledMessage) { + return ( + + {children} + + ); + } + + return <>{children}; +}; + +function getRestrictionReasonLabel( + canEditSynthetics = true, + canUpdatePrivateMonitor = true, + canAddPrivateMonitor = true +): string | undefined { + return !canEditSynthetics + ? CANNOT_PERFORM_ACTION_SYNTHETICS + : !canUpdatePrivateMonitor + ? CANNOT_PERFORM_ACTION_FLEET + : !canAddPrivateMonitor + ? PRIVATE_LOCATIONS_NOT_ALLOWED_MESSAGE + : undefined; +} + +export const NEED_PERMISSIONS = i18n.translate( + 'xpack.synthetics.monitorManagement.needPermissions', + { + defaultMessage: 'Need permissions', + } +); + +export const NEED_FLEET_READ_AGENT_POLICIES_PERMISSION = i18n.translate( + 'xpack.synthetics.monitorManagement.needFleetReadAgentPoliciesPermission', + { + defaultMessage: + 'You are not authorized to access Fleet. Fleet permissions are required to create new private locations.', + } +); + +export const CANNOT_SAVE_INTEGRATION_LABEL = i18n.translate( + 'xpack.synthetics.monitorManagement.cannotSaveIntegration', + { + defaultMessage: + 'You are not authorized to update integrations. Integrations write permissions are required.', + } +); + +const CANNOT_PERFORM_ACTION_FLEET = i18n.translate( + 'xpack.synthetics.monitorManagement.noFleetPermission', + { + defaultMessage: + 'You are not authorized to perform this action. Integrations write permissions are required.', + } +); + +const CANNOT_PERFORM_ACTION_SYNTHETICS = i18n.translate( + 'xpack.synthetics.monitorManagement.noSyntheticsPermissions', + { + defaultMessage: 'You do not have sufficient permissions to perform this action.', + } +); + +const PRIVATE_LOCATIONS_NOT_ALLOWED_MESSAGE = i18n.translate( + 'xpack.synthetics.monitorManagement.privateLocationsNotAllowedMessage', + { + defaultMessage: + 'You do not have permission to add monitors to private locations. Contact your administrator to request access.', + } +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/edit_monitor.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/edit_monitor.tsx deleted file mode 100644 index 3573d2cffa133..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/links/edit_monitor.tsx +++ /dev/null @@ -1,33 +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 { EuiButton } from '@elastic/eui'; -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { useParams } from 'react-router-dom'; -import { useSyntheticsSettingsContext } from '../../../contexts'; - -export const EditMonitorLink = () => { - const { basePath } = useSyntheticsSettingsContext(); - - const { monitorId } = useParams<{ monitorId: string }>(); - - return ( - - {EDIT_MONITOR} - - ); -}; - -const EDIT_MONITOR = i18n.translate('xpack.synthetics.monitorSummary.editMonitor', { - defaultMessage: 'Edit monitor', -}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/simple_monitor_form.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/simple_monitor_form.tsx index 68499e7612652..114be36195215 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/simple_monitor_form.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/getting_started/simple_monitor_form.tsx @@ -18,8 +18,11 @@ import React, { useState } from 'react'; import { i18n } from '@kbn/i18n'; import { useSimpleMonitor } from './use_simple_monitor'; import { ServiceLocationsField } from './form_fields/service_locations'; -import { ConfigKey, ServiceLocations } from '../../../../../common/runtime_types'; +import { ConfigKey, ServiceLocation, ServiceLocations } from '../../../../../common/runtime_types'; +import { useCanEditSynthetics } from '../../../../hooks/use_capabilities'; import { useFormWrapped } from '../../../../hooks/use_form_wrapped'; +import { useFleetPermissions } from '../../hooks'; +import { NoPermissionsTooltip } from '../common/components/permissions'; export interface SimpleFormData { urls: string; @@ -32,6 +35,7 @@ export const SimpleMonitorForm = () => { register, handleSubmit, formState: { errors, isValid, isSubmitted }, + getValues, } = useFormWrapped({ mode: 'onSubmit', reValidateMode: 'onChange', @@ -47,6 +51,13 @@ export const SimpleMonitorForm = () => { const { loading, data: newMonitor } = useSimpleMonitor({ monitorData }); + const canEditSynthetics = useCanEditSynthetics(); + const { canSaveIntegrations } = useFleetPermissions(); + const hasAnyPrivateLocationSelected = (getValues(ConfigKey.LOCATIONS) as ServiceLocations)?.some( + ({ isServiceManaged }: ServiceLocation) => !isServiceManaged + ); + const canSavePrivateLocation = !hasAnyPrivateLocationSelected || canSaveIntegrations; + const hasURLError = !!errors?.[ConfigKey.URLS]; return ( @@ -77,15 +88,21 @@ export const SimpleMonitorForm = () => { - - {CREATE_MONITOR_LABEL} - + + {CREATE_MONITOR_LABEL} + + diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/submit.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/submit.tsx index ba29b5ca3fd6d..37211860d6df2 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/submit.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/form/submit.tsx @@ -12,9 +12,12 @@ import { i18n } from '@kbn/i18n'; import { useFormContext } from 'react-hook-form'; import { FETCH_STATUS } from '@kbn/observability-plugin/public'; import { RunTestButton } from './run_test_btn'; +import { useCanEditSynthetics } from '../../../../../hooks/use_capabilities'; +import { useFleetPermissions } from '../../../hooks'; import { useMonitorSave } from '../hooks/use_monitor_save'; +import { NoPermissionsTooltip } from '../../common/components/permissions'; import { DeleteMonitor } from '../../monitors_page/management/monitor_list_table/delete_monitor'; -import { ConfigKey, SourceType, SyntheticsMonitor } from '../types'; +import { ConfigKey, ServiceLocation, SourceType, SyntheticsMonitor } from '../types'; import { format } from './formatter'; import { MONITORS_ROUTE } from '../../../../../../common/constants'; @@ -25,6 +28,7 @@ export const ActionBar = ({ readOnly = false }: { readOnly: boolean }) => { const { handleSubmit, formState: { errors, defaultValues }, + getValues, } = useFormContext(); const [monitorPendingDeletion, setMonitorPendingDeletion] = useState( @@ -35,6 +39,13 @@ export const ActionBar = ({ readOnly = false }: { readOnly: boolean }) => { const { status, loading, isEdit } = useMonitorSave({ monitorData }); + const canEditSynthetics = useCanEditSynthetics(); + const { canSaveIntegrations } = useFleetPermissions(); + const hasAnyPrivateLocationSelected = getValues(ConfigKey.LOCATIONS)?.some( + ({ isServiceManaged }: ServiceLocation) => !isServiceManaged + ); + const canSavePrivateLocation = !hasAnyPrivateLocationSelected || canSaveIntegrations; + const formSubmitter = (formData: Record) => { if (!Object.keys(errors).length) { setMonitorData(format(formData, readOnly)); @@ -68,15 +79,21 @@ export const ActionBar = ({ readOnly = false }: { readOnly: boolean }) => {
- - {isEdit ? UPDATE_MONITOR_LABEL : CREATE_MONITOR_LABEL} - + + {isEdit ? UPDATE_MONITOR_LABEL : CREATE_MONITOR_LABEL} + +
{monitorPendingDeletion && ( diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/edit_monitor_link.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/edit_monitor_link.tsx new file mode 100644 index 0000000000000..82fc256772921 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/edit_monitor_link.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 from 'react'; +import { useParams } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; +import { EuiButton } from '@elastic/eui'; + +import { EncryptedSyntheticsMonitor } from '../../../../../../common/runtime_types'; +import { useCanEditSynthetics } from '../../../../../hooks/use_capabilities'; +import { useSyntheticsSettingsContext } from '../../../contexts'; +import { useCanUpdatePrivateMonitor } from '../../../hooks'; +import { NoPermissionsTooltip } from '../../common/components/permissions'; +import { useSelectedMonitor } from '../hooks/use_selected_monitor'; + +export const EditMonitorLink = () => { + const { basePath } = useSyntheticsSettingsContext(); + + const { monitorId } = useParams<{ monitorId: string }>(); + const { monitor } = useSelectedMonitor(); + + const canEditSynthetics = useCanEditSynthetics(); + const canUpdatePrivateMonitor = useCanUpdatePrivateMonitor(monitor as EncryptedSyntheticsMonitor); + const isLinkDisabled = !canEditSynthetics || !canUpdatePrivateMonitor; + const linkProps = isLinkDisabled + ? { disabled: true } + : { href: `${basePath}/app/synthetics/edit-monitor/${monitorId}` }; + + return ( + + + {EDIT_MONITOR} + + + ); +}; + +const EDIT_MONITOR = i18n.translate('xpack.synthetics.monitorSummary.editMonitor', { + defaultMessage: 'Edit monitor', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/route_config.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/route_config.tsx index 8acf81c10e778..1a2ab66b06ab6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/route_config.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/route_config.tsx @@ -12,7 +12,6 @@ import { EuiIcon, EuiPageHeaderProps } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { MonitorNotFoundPage } from './monitor_not_found_page'; import { MonitorDetailsPageTitle } from './monitor_details_page_title'; -import { EditMonitorLink } from '../common/links/edit_monitor'; import { RunTestManually } from './run_test_manually'; import { MonitorDetailsLastRun } from './monitor_details_last_run'; import { MonitorDetailsStatus } from './monitor_details_status'; @@ -20,6 +19,7 @@ import { MonitorDetailsLocation } from './monitor_details_location'; import { MonitorErrors } from './monitor_errors/monitor_errors'; import { MonitorHistory } from './monitor_history/monitor_history'; import { MonitorSummary } from './monitor_summary/monitor_summary'; +import { EditMonitorLink } from './monitor_summary/edit_monitor_link'; import { MonitorDetailsPage } from './monitor_details_page'; import { MONITOR_ERRORS_ROUTE, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx index f60423ae2bf4b..410132d6b49b3 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/run_test_manually.tsx @@ -9,7 +9,11 @@ import { EuiButton, EuiToolTip } from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; import { useDispatch, useSelector } from 'react-redux'; -import { TEST_NOW_ARIA_LABEL, TEST_SCHEDULED_LABEL } from '../monitor_add_edit/form/run_test_btn'; +import { + TEST_NOW_ARIA_LABEL, + TEST_SCHEDULED_LABEL, + PRIVATE_AVAILABLE_LABEL, +} from '../monitor_add_edit/form/run_test_btn'; import { useSelectedMonitor } from './hooks/use_selected_monitor'; import { manualTestMonitorAction, @@ -21,20 +25,22 @@ export const RunTestManually = () => { const { monitor } = useSelectedMonitor(); - const hasPublicLocation = () => { - return monitor?.locations.some((loc) => loc.isServiceManaged); - }; + const hasPublicLocation = monitor?.locations.some((loc) => loc.isServiceManaged); const testInProgress = useSelector(manualTestRunInProgressSelector(monitor?.config_id)); - const content = testInProgress ? TEST_SCHEDULED_LABEL : TEST_NOW_ARIA_LABEL; + const content = !hasPublicLocation + ? PRIVATE_AVAILABLE_LABEL + : testInProgress + ? TEST_SCHEDULED_LABEL + : TEST_NOW_ARIA_LABEL; return ( { if (monitor) { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/create_monitor_button.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/create_monitor_button.tsx index a476662f9ad8c..690168fe66813 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/create_monitor_button.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/create_monitor_button.tsx @@ -7,7 +7,9 @@ import React, { useContext } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiButton } from '@elastic/eui'; -import { useEnablement } from '../../hooks'; +import { useCanEditSynthetics } from '../../../../hooks/use_capabilities'; +import { NoPermissionsTooltip } from '../common/components/permissions'; +import { useEnablement, useFleetPermissions, useLocations } from '../../hooks'; import { MONITOR_ADD_ROUTE } from '../../../../../common/constants'; import { SyntheticsSettingsContext } from '../../contexts/synthetics_settings_context'; @@ -19,20 +21,33 @@ export const CreateMonitorButton: React.FC = () => { enablement: { isEnabled }, } = useEnablement(); + const canEditSynthetics = useCanEditSynthetics(); + const { canSaveIntegrations } = useFleetPermissions(); + const { locations } = useLocations(); + + const hasPublicLocation = locations.some((loc) => loc.isServiceManaged); + + const canAddMonitor = canEditSynthetics && (hasPublicLocation || canSaveIntegrations); + return ( - - - + + + + ); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx index 57e8d846130cf..dd56da1e7e563 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/columns.tsx @@ -14,6 +14,7 @@ import { isStatusEnabled, toggleStatusAlert, } from '../../../../../../../common/runtime_types/monitor_management/alert_config'; +import { NoPermissionsTooltip } from '../../../common/components/permissions'; import { TagsBadges } from '../../../common/components/tag_badges'; import { useMonitorAlertEnable } from '../../../../hooks/use_monitor_alert_enable'; import * as labels from './labels'; @@ -27,6 +28,7 @@ import { SyntheticsMonitorSchedule, } from '../../../../../../../common/runtime_types'; +import { canUpdatePrivateMonitor, useFleetPermissions } from '../../../../hooks'; import { MonitorTypeBadge } from '../../../common/components/monitor_type_badge'; import { getFrequencyLabel } from './labels'; import { MonitorEnabled } from './monitor_enabled'; @@ -46,6 +48,7 @@ export function useMonitorListColumns({ const history = useHistory(); const { alertStatus, updateAlertEnabledState } = useMonitorAlertEnable(); + const { canSaveIntegrations } = useFleetPermissions(); const isActionLoading = (fields: EncryptedSyntheticsSavedMonitor) => { return alertStatus(fields[ConfigKey.CONFIG_ID]) === FETCH_STATUS.LOADING; @@ -161,11 +164,21 @@ export function useMonitorListColumns({ { 'data-test-subj': 'syntheticsMonitorEditAction', isPrimary: true, - name: labels.EDIT_LABEL, + name: (fields) => ( + + {labels.EDIT_LABEL} + + ), description: labels.EDIT_LABEL, icon: 'pencil', type: 'icon', - enabled: (fields) => canEditSynthetics && !isActionLoading(fields), + enabled: (fields) => + canEditSynthetics && + !isActionLoading(fields) && + canUpdatePrivateMonitor(fields, canSaveIntegrations), onClick: (fields) => { history.push({ pathname: `/edit-monitor/${fields[ConfigKey.CONFIG_ID]}`, @@ -175,12 +188,22 @@ export function useMonitorListColumns({ { 'data-test-subj': 'syntheticsMonitorDeleteAction', isPrimary: true, - name: labels.DELETE_LABEL, + name: (fields) => ( + + {labels.DELETE_LABEL} + + ), description: labels.DELETE_LABEL, icon: 'trash', type: 'icon', color: 'danger', - enabled: (fields) => canEditSynthetics && !isActionLoading(fields), + enabled: (fields) => + canEditSynthetics && + !isActionLoading(fields) && + canUpdatePrivateMonitor(fields, canSaveIntegrations), onClick: (fields) => { setMonitorPendingDeletion(fields); }, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_enabled.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_enabled.tsx index e4354a2592168..429f53a754c80 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_enabled.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/monitor_enabled.tsx @@ -9,10 +9,11 @@ import React, { useMemo } from 'react'; import { EuiSwitch, EuiSwitchEvent, EuiLoadingSpinner } from '@elastic/eui'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { FETCH_STATUS } from '@kbn/observability-plugin/public'; -import { useCanEditSynthetics } from '../../../../../../hooks/use_capabilities'; import { ConfigKey, EncryptedSyntheticsMonitor } from '../../../../../../../common/runtime_types'; +import { useCanEditSynthetics } from '../../../../../../hooks/use_capabilities'; +import { useCanUpdatePrivateMonitor, useMonitorEnableHandler } from '../../../../hooks'; +import { NoPermissionsTooltip } from '../../../common/components/permissions'; import * as labels from './labels'; -import { useMonitorEnableHandler } from '../../../../hooks/use_monitor_enable_handler'; interface Props { configId: string; @@ -29,7 +30,8 @@ export const MonitorEnabled = ({ initialLoading = false, isSwitchable = true, }: Props) => { - const isDisabled = !useCanEditSynthetics(); + const canUpdatePrivateMonitor = useCanUpdatePrivateMonitor(monitor); + const canEditSynthetics = useCanEditSynthetics(); const monitorName = monitor[ConfigKey.NAME]; const statusLabels = useMemo(() => { @@ -55,22 +57,29 @@ export const MonitorEnabled = ({ updateMonitorEnabledState(checked); }; + const enabledDisableLabel = enabled ? labels.DISABLE_MONITOR_LABEL : labels.ENABLE_MONITOR_LABEL; + return ( <> {isLoading || initialLoading ? ( ) : ( - + + + )} ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx index 495902b454527..95605d5de0364 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/actions_popover.tsx @@ -27,12 +27,21 @@ import { import { toggleStatusAlert } from '../../../../../../../common/runtime_types/monitor_management/alert_config'; import { useSelectedMonitor } from '../../../monitor_details/hooks/use_selected_monitor'; import { useMonitorAlertEnable } from '../../../../hooks/use_monitor_alert_enable'; -import { ConfigKey, MonitorOverviewItem } from '../../../../../../../common/runtime_types'; -import { useMonitorEnableHandler } from '../../../../hooks/use_monitor_enable_handler'; +import { + ConfigKey, + EncryptedSyntheticsMonitor, + MonitorOverviewItem, +} from '../../../../../../../common/runtime_types'; +import { useCanEditSynthetics } from '../../../../../../hooks/use_capabilities'; +import { + useMonitorEnableHandler, + useLocationName, + useCanUpdatePrivateMonitor, +} from '../../../../hooks'; import { setFlyoutConfig } from '../../../../state/overview/actions'; import { useEditMonitorLocator } from '../../hooks/use_edit_monitor_locator'; import { useMonitorDetailLocator } from '../../../../hooks/use_monitor_detail_locator'; -import { useLocationName } from '../../../../hooks'; +import { NoPermissionsTooltip } from '../../../common/components/permissions'; type PopoverPosition = 'relative' | 'default'; @@ -113,6 +122,10 @@ export function ActionsPopover({ const editUrl = useEditMonitorLocator({ configId: monitor.configId }); const { monitor: monitorFields } = useSelectedMonitor(monitor.configId); + const canEditSynthetics = useCanEditSynthetics(); + const canUpdatePrivateMonitor = useCanUpdatePrivateMonitor( + monitorFields as EncryptedSyntheticsMonitor + ); const labels = useMemo( () => ({ @@ -190,13 +203,29 @@ export function ActionsPopover({ }, }, { - name: actionsMenuEditMonitorName, + name: ( + + {actionsMenuEditMonitorName} + + ), icon: 'pencil', + disabled: !canEditSynthetics || !canUpdatePrivateMonitor, href: editUrl, }, { - name: enableLabel, + name: ( + + {enableLabel} + + ), icon: 'invert', + disabled: !canEditSynthetics || !canUpdatePrivateMonitor, onClick: () => { if (status !== FETCH_STATUS.LOADING) { updateMonitorEnabledState(!monitor.isEnabled); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx index a7f3e51b7e3a5..c87aa157eeffa 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { FormProvider } from 'react-hook-form'; import { EuiButtonEmpty, - EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiFlyoutBody, @@ -20,11 +19,11 @@ import { EuiButton, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { usePrivateLocationPermissions } from './hooks/use_private_location_permission'; +import { useFleetPermissions } from '../../../hooks/use_fleet_permissions'; import { useFormWrapped } from '../../../../../hooks/use_form_wrapped'; import { PrivateLocation } from '../../../../../../common/runtime_types'; +import { FleetPermissionsCallout } from '../../common/components/permissions'; import { LocationForm } from './location_form'; -import { NEED_FLEET_READ_AGENT_POLICIES_PERMISSION, NEED_PERMISSIONS } from './translations'; export const AddLocationFlyout = ({ onSubmit, @@ -55,7 +54,7 @@ export const AddLocationFlyout = ({ const { handleSubmit } = form; - const { canReadAgentPolicies } = usePrivateLocationPermissions(); + const { canReadAgentPolicies } = useFleetPermissions(); const closeFlyout = () => { setIsOpen(false); @@ -70,11 +69,8 @@ export const AddLocationFlyout = ({ - {!canReadAgentPolicies && ( - -

{NEED_FLEET_READ_AGENT_POLICIES_PERMISSION}

-
- )} + {!canReadAgentPolicies && } +
diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/delete_location.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/delete_location.tsx index 782164b8db8fd..6d2c95cac70ae 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/delete_location.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/delete_location.tsx @@ -9,6 +9,8 @@ import React, { useState } from 'react'; import { EuiButtonIcon, EuiConfirmModal, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { useSyntheticsSettingsContext } from '../../../contexts'; +import { useFleetPermissions } from '../../../hooks'; +import { CANNOT_SAVE_INTEGRATION_LABEL } from '../../common/components/permissions'; export const DeleteLocation = ({ loading, @@ -27,9 +29,18 @@ export const DeleteLocation = ({ const canDelete = monCount === 0; const { canSave } = useSyntheticsSettingsContext(); + const { canSaveIntegrations } = useFleetPermissions(); const [isModalOpen, setIsModalOpen] = useState(false); + const deleteDisabledReason = !canSaveIntegrations + ? CANNOT_SAVE_INTEGRATION_LABEL + : i18n.translate('xpack.synthetics.monitorManagement.cannotDelete.description', { + defaultMessage: `This location cannot be deleted, because it has {monCount, number} {monCount, plural,one {monitor} other {monitors}} running. + Please remove this location from your monitors before deleting this location.`, + values: { monCount }, + }); + const deleteModal = ( {isModalOpen && deleteModal} - + { const tags = item.tags || []; @@ -125,19 +126,16 @@ export const PrivateLocationsTable = ({ const setIsAddingNew = (val: boolean) => dispatch(setAddingNewPrivateLocation(val)); - const { fleet } = useKibana().services; - - const hasFleetPermissions = Boolean(fleet?.authz.fleet.readAgentPolicies); - const renderToolRight = () => { return [ setIsAddingNew(true)} iconType="plusInCircle" + title={!canSaveIntegrations ? CANNOT_SAVE_INTEGRATION_LABEL : undefined} > {ADD_LABEL} , diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx index 0aa5e181c5ac1..d697d011e5841 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx @@ -5,12 +5,10 @@ * 2.0. */ import React, { useEffect } from 'react'; -import { EuiCallOut } from '@elastic/eui'; import { useDispatch, useSelector } from 'react-redux'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; import { LoadingState } from '../../monitors_page/overview/overview/monitor_detail_flyout'; import { PrivateLocationsTable } from './locations_table'; -import { ClientPluginsStart } from '../../../../../plugin'; +import { useFleetPermissions } from '../../../hooks'; import { ManageEmptyState } from './manage_empty_state'; import { AddLocationFlyout } from './add_location_flyout'; import { useLocationsAPI } from './hooks/use_locations_api'; @@ -21,7 +19,7 @@ import { } from '../../../state/private_locations'; import { PrivateLocation } from '../../../../../../common/runtime_types'; import { getServiceLocations } from '../../../state'; -import { NEED_FLEET_READ_AGENT_POLICIES_PERMISSION, NEED_PERMISSIONS } from './translations'; +import { FleetPermissionsCallout } from '../../common/components/permissions'; export const ManagePrivateLocations = () => { const dispatch = useDispatch(); @@ -32,9 +30,7 @@ export const ManagePrivateLocations = () => { const { onSubmit, loading, privateLocations, onDelete, deleteLoading } = useLocationsAPI(); - const { fleet } = useKibana().services; - - const hasFleetPermissions = Boolean(fleet?.authz.fleet.readAgentPolicies); + const { canReadAgentPolicies } = useFleetPermissions(); useEffect(() => { dispatch(getAgentPoliciesAction.get()); @@ -47,13 +43,15 @@ export const ManagePrivateLocations = () => { return ( <> + {!canReadAgentPolicies && } + {loading ? ( ) : ( { /> )} - {!hasFleetPermissions && ( - -

{NEED_FLEET_READ_AGENT_POLICIES_PERMISSION}

-
- )} + {isAddingNew ? ( { - const { canReadAgentPolicies } = usePrivateLocationPermissions(); + const { canReadAgentPolicies } = useFleetPermissions(); const { basePath } = useSyntheticsSettingsContext(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/translations.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/translations.ts deleted file mode 100644 index f67305d739988..0000000000000 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/translations.ts +++ /dev/null @@ -1,23 +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 NEED_PERMISSIONS = i18n.translate( - 'xpack.synthetics.monitorManagement.needPermissions', - { - defaultMessage: 'Need permissions', - } -); - -export const NEED_FLEET_READ_AGENT_POLICIES_PERMISSION = i18n.translate( - 'xpack.synthetics.monitorManagement.needFleetReadAgentPoliciesPermission', - { - defaultMessage: - 'You are not authorized to access Fleet. Fleet permissions are required to create new private locations.', - } -); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts index 5903c2bb0beb6..25730ab50f7a1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts @@ -18,3 +18,5 @@ export * from './use_status_by_location'; export * from './use_status_by_location_overview'; export * from './use_composite_image'; export * from './use_dimensions'; +export * from './use_fleet_permissions'; +export * from './use_monitor_enable_handler'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_private_location_permission.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_fleet_permissions.ts similarity index 52% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_private_location_permission.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_fleet_permissions.ts index f62cc05f8fd0e..bbd5aa4f681bf 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_private_location_permission.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_fleet_permissions.ts @@ -6,20 +6,38 @@ */ import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { BrowserFields, ConfigKey } from '../../../../../../../common/runtime_types'; -import { ClientPluginsStart } from '../../../../../../plugin'; +import { ClientPluginsStart } from '../../../plugin'; +import { + BrowserFields, + ConfigKey, + EncryptedSyntheticsMonitor, +} from '../../../../common/runtime_types'; -export function usePrivateLocationPermissions(monitor?: BrowserFields) { +export function useFleetPermissions() { const { fleet } = useKibana().services; const canSaveIntegrations: boolean = Boolean(fleet?.authz.integrations.writeIntegrationPolicies); const canReadAgentPolicies = Boolean(fleet?.authz.fleet.readAgentPolicies); + return { + canReadAgentPolicies, + canSaveIntegrations, + }; +} + +export function useCanUpdatePrivateMonitor(monitor: EncryptedSyntheticsMonitor) { + const { canSaveIntegrations } = useFleetPermissions(); + + return canUpdatePrivateMonitor(monitor, canSaveIntegrations); +} + +export function canUpdatePrivateMonitor( + monitor: EncryptedSyntheticsMonitor, + canSaveIntegrations: boolean +) { const locations = (monitor as BrowserFields)?.[ConfigKey.LOCATIONS]; const hasPrivateLocation = locations?.some((location) => !location.isServiceManaged); - const canUpdatePrivateMonitor = !(hasPrivateLocation && !canSaveIntegrations); - - return { canUpdatePrivateMonitor, canReadAgentPolicies }; + return !(hasPrivateLocation && !canSaveIntegrations); } From d2f86398ecc76c0a8a9abdbadcb6d37a693886b9 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Thu, 9 Feb 2023 18:09:39 +0200 Subject: [PATCH 037/203] [UA] skip system indices migration status check if `featureSet.migrateSystemIndices` is set to `false` (#150710) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../server/routes/status.test.ts | 54 +++++++++++++++---- .../upgrade_assistant/server/routes/status.ts | 22 +++++++- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts index 97a87a29bda88..21daa3e69697e 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.test.ts @@ -8,12 +8,13 @@ import { kibanaResponseFactory } from '@kbn/core/server'; import { handleEsError } from '../shared_imports'; -import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; +import { createMockRouter, routeHandlerContextMock } from './__mocks__/routes.mock'; import { createRequestMock } from './__mocks__/request.mock'; import { registerUpgradeStatusRoute } from './status'; import { getESUpgradeStatus } from '../lib/es_deprecations_status'; import { getKibanaUpgradeStatus } from '../lib/kibana_status'; import { getESSystemIndicesMigrationStatus } from '../lib/es_system_indices_migration'; +import type { FeatureSet } from '../../common/types'; jest.mock('../lib/es_version_precheck', () => ({ versionCheckHandlerWrapper: (a: any) => a, @@ -86,31 +87,33 @@ const systemIndicesNoMigrationResponse = { }; describe('Status API', () => { - let mockRouter: MockRouter; - let routeDependencies: any; - - beforeEach(() => { - mockRouter = createMockRouter(); - routeDependencies = { + const registerRoutes = (featureSetOverrides: Partial = {}) => { + const mockRouter = createMockRouter(); + const routeDependencies: any = { config: { featureSet: { mlSnapshots: true, migrateSystemIndices: true, reindexCorrectiveActions: true, + ...featureSetOverrides, }, }, router: mockRouter, lib: { handleEsError }, }; + registerUpgradeStatusRoute(routeDependencies); - }); - afterEach(() => { - jest.resetAllMocks(); - }); + return { mockRouter, routeDependencies }; + }; describe('GET /api/upgrade_assistant/status', () => { + afterEach(() => { + jest.resetAllMocks(); + }); + it('returns readyForUpgrade === false if Kibana or ES contain critical deprecations and no system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); getESUpgradeStatusMock.mockResolvedValue(esDeprecationsResponse); getKibanaUpgradeStatusMock.mockResolvedValue({ @@ -124,6 +127,7 @@ describe('Status API', () => { pathPattern: '/api/upgrade_assistant/status', })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); expect(resp.status).toEqual(200); expect(resp.payload).toEqual({ readyForUpgrade: false, @@ -133,6 +137,7 @@ describe('Status API', () => { }); it('returns readyForUpgrade === false if Kibana or ES contain critical deprecations and system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); getESUpgradeStatusMock.mockResolvedValue(esDeprecationsResponse); getKibanaUpgradeStatusMock.mockResolvedValue({ @@ -146,6 +151,7 @@ describe('Status API', () => { pathPattern: '/api/upgrade_assistant/status', })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); expect(resp.status).toEqual(200); expect(resp.payload).toEqual({ readyForUpgrade: false, @@ -155,6 +161,7 @@ describe('Status API', () => { }); it('returns readyForUpgrade === false if no critical Kibana or ES deprecations but system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); getESUpgradeStatusMock.mockResolvedValue(esNoDeprecationsResponse); getKibanaUpgradeStatusMock.mockResolvedValue({ @@ -168,6 +175,7 @@ describe('Status API', () => { pathPattern: '/api/upgrade_assistant/status', })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); expect(resp.status).toEqual(200); expect(resp.payload).toEqual({ readyForUpgrade: false, @@ -177,6 +185,7 @@ describe('Status API', () => { }); it('returns readyForUpgrade === true if there are no critical deprecations and no system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); getESUpgradeStatusMock.mockResolvedValue(esNoDeprecationsResponse); getKibanaUpgradeStatusMock.mockResolvedValue({ @@ -197,7 +206,30 @@ describe('Status API', () => { }); }); + it('skips ES system indices migration check when featureSet.migrateSystemIndices is set to false', async () => { + const { routeDependencies } = registerRoutes({ migrateSystemIndices: false }); + getESUpgradeStatusMock.mockResolvedValue(esNoDeprecationsResponse); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 0, + }); + + getESSystemIndicesMigrationStatusMock.mockResolvedValue(systemIndicesMigrationResponse); + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); + + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(0); + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + readyForUpgrade: true, + details: 'All deprecation warnings have been resolved.', + }); + }); + it('returns an error if it throws', async () => { + const { routeDependencies } = registerRoutes(); getESUpgradeStatusMock.mockRejectedValue(new Error('test error')); getKibanaUpgradeStatusMock.mockResolvedValue({ diff --git a/x-pack/plugins/upgrade_assistant/server/routes/status.ts b/x-pack/plugins/upgrade_assistant/server/routes/status.ts index 409fb72e33164..3f6f90d8823f0 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/status.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/status.ts @@ -37,9 +37,27 @@ export function registerUpgradeStatusRoute({ esClient, featureSet ); - // Fetch system indices migration status + + const getSystemIndicesMigrationStatus = async () => { + /** + * Skip system indices migration status check if `featureSet.migrateSystemIndices` + * is set to `false`. This flag is enabled from configs for major version stack ugprades. + * returns `migration_status: 'NO_MIGRATION_NEEDED'` to indicate no migation needed. + */ + if (!featureSet.migrateSystemIndices) { + return { + migration_status: 'NO_MIGRATION_NEEDED', + features: [], + }; + } + + // Fetch system indices migration status from ES + return await getESSystemIndicesMigrationStatus(esClient.asCurrentUser); + }; + const { migration_status: systemIndicesMigrationStatus, features } = - await getESSystemIndicesMigrationStatus(esClient.asCurrentUser); + await getSystemIndicesMigrationStatus(); + const notMigratedSystemIndices = features.filter( (feature) => feature.migration_status !== 'NO_MIGRATION_NEEDED' ).length; From d8276307e72e81d1e46ec198f222f1d1db12cbfc Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Thu, 9 Feb 2023 17:19:00 +0100 Subject: [PATCH 038/203] [Fleet] fixed prerelease integration tests (#150721) ## Summary Changed prerelease integration tests to use other package than endpoint, so it is not impacted by new versions. Fixes https://github.com/elastic/kibana/issues/149844 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../apis/epm/install_prerelease.ts | 24 ++++++++---------- .../endpoint/endpoint-8.7.0-next.zip | Bin 1477466 -> 0 bytes .../1.0.0/data_stream/test/fields/fields.yml | 16 ++++++++++++ .../1.0.0/data_stream/test/manifest.yml | 3 +++ .../prerelease/1.0.0/docs/README.md | 3 +++ .../1.0.0/img/logo_prerelease_64_color.svg | 7 +++++ .../prerelease/1.0.0/manifest.yml | 21 +++++++++++++++ .../data_stream/test/fields/fields.yml | 16 ++++++++++++ .../1.0.1-next/data_stream/test/manifest.yml | 3 +++ .../prerelease/1.0.1-next/docs/README.md | 3 +++ .../img/logo_prerelease_64_color.svg | 7 +++++ .../prerelease/1.0.1-next/manifest.yml | 21 +++++++++++++++ 12 files changed, 111 insertions(+), 13 deletions(-) delete mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/endpoint/endpoint-8.7.0-next.zip create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/fields/fields.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/manifest.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/docs/README.md create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/img/logo_prerelease_64_color.svg create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/manifest.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/fields/fields.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/manifest.yml create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/docs/README.md create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/img/logo_prerelease_64_color.svg create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/manifest.yml diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts index c599556a445a3..714d53513ba4d 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts @@ -22,9 +22,7 @@ export default function (providerContext: FtrProviderContext) { await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx'); }; - // Failing: See https://github.com/elastic/kibana/issues/149844 - // FLAKY: https://github.com/elastic/kibana/issues/150343 - describe.skip('installs package that has a prerelease version', async () => { + describe('installs package that has a prerelease version', async () => { skipIfNoDockerRegistry(providerContext); setupFleetAndAgents(providerContext); @@ -39,21 +37,21 @@ export default function (providerContext: FtrProviderContext) { await supertest .post(`/api/fleet/epm/packages/${testPackage}/${testPackageVersion}`) .set('kbn-xsrf', 'xxxx') + .send({ force: true }) .expect(200); }); - const pkg = 'endpoint'; - const gaVersion = '8.6.1'; - const betaVersion = '8.7.0-next'; + const gaVersion = '1.0.0'; + const betaVersion = '1.0.1-next'; afterEach(async () => { - await deletePackage(pkg, gaVersion); - await deletePackage(pkg, betaVersion); + await deletePackage(testPackage, gaVersion); + await deletePackage(testPackage, betaVersion); }); it('should install the GA package correctly', async function () { const response = await supertest - .post(`/api/fleet/epm/packages/${pkg}/${gaVersion}`) + .post(`/api/fleet/epm/packages/${testPackage}/${gaVersion}`) .set('kbn-xsrf', 'xxxx') .send({ force: true }) .expect(200); @@ -63,7 +61,7 @@ export default function (providerContext: FtrProviderContext) { it('should install the GA package when no version is provided', async function () { const response = await supertest - .post(`/api/fleet/epm/packages/${pkg}`) + .post(`/api/fleet/epm/packages/${testPackage}`) .set('kbn-xsrf', 'xxxx') .send({ force: true }) .expect(200); @@ -73,7 +71,7 @@ export default function (providerContext: FtrProviderContext) { it('should install the beta package when no version is provided and prerelease is true', async function () { const response = await supertest - .post(`/api/fleet/epm/packages/${pkg}?prerelease=true`) + .post(`/api/fleet/epm/packages/${testPackage}?prerelease=true`) .set('kbn-xsrf', 'xxxx') .send({ force: true }) // using force to ignore package verification error .expect(200); @@ -85,7 +83,7 @@ export default function (providerContext: FtrProviderContext) { const response = await supertest .post(`/api/fleet/epm/packages/_bulk?prerelease=true`) .set('kbn-xsrf', 'xxxx') - .send({ packages: ['endpoint'], force: true }) + .send({ packages: ['prerelease'], force: true }) .expect(200); expect(response.body.items[0].version).equal(betaVersion); @@ -95,7 +93,7 @@ export default function (providerContext: FtrProviderContext) { const response = await supertest .post(`/api/fleet/epm/packages/_bulk`) .set('kbn-xsrf', 'xxxx') - .send({ packages: ['endpoint'], force: true }) + .send({ packages: ['prerelease'], force: true }) .expect(200); expect(response.body.items[0].version).equal(gaVersion); diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/endpoint/endpoint-8.7.0-next.zip b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/endpoint/endpoint-8.7.0-next.zip deleted file mode 100644 index 2002c1c8c20026fcdf8107808e181460c97be15c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1477466 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℘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

>$QDCz_N9rV=l`y3L&#Qc@^f6VQG z>4Z3)!pM$N(wRrte1WryEve>Fy`ERxf2wV{^GEgb>+_h~;kv)05wgzOp1;3i9<}S) z#rLb}Y@S2(x}T$|QP20kMBWtCs&=yz_Hs46rDFXd>|lQ2z#5xU`-f40L8l#`I2G8w zqlIeB4ra-@Uw9tPy%R619B}d~3M!CtkC@xw#Op-R?D%Zzxyq7@B+X$6fKyNCn{prW zHF3V8&^bL$yiFMsYjA?;xbWW&>G&1Rl1iqAR~SWk1|^aa5$db_c!GtXrIsklOZ3r{ zl6)DVwldLdjiS1M4Usk=yjn+M0H{i~`*6nQeGH`(l0DnXb4w+u0qyU4 zAxwevl8ocGEJW$LXW-B5%0ArH?xR<0T;yI>|!cPlx1oY*5cb(`4 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 diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/fields/fields.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/manifest.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/manifest.yml new file mode 100644 index 0000000000000..17c33c745ce74 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/data_stream/test/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: logs diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/docs/README.md b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/docs/README.md new file mode 100644 index 0000000000000..0002afd9cdfc0 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing a prerelease package diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/img/logo_prerelease_64_color.svg b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/img/logo_prerelease_64_color.svg new file mode 100644 index 0000000000000..b03007a76ffcc --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/img/logo_prerelease_64_color.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/manifest.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/manifest.yml new file mode 100644 index 0000000000000..231cf1ed668b7 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.0/manifest.yml @@ -0,0 +1,21 @@ +format_version: 1.0.0 +name: prerelease +title: Prerelease package +description: This is a test package for testing that parsing a prerelease version works +version: 1.0.0 +categories: ['security'] +type: integration +license: basic +owner: + github: elastic/fleet + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_prerelease_64_color.svg' + size: '16x16' + type: 'image/svg+xml' diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/fields/fields.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/fields/fields.yml new file mode 100644 index 0000000000000..6e003ed0ad147 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/fields/fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.type + type: constant_keyword + description: > + Data stream type. +- name: data_stream.dataset + type: constant_keyword + description: > + Data stream dataset. +- name: data_stream.namespace + type: constant_keyword + description: > + Data stream namespace. +- name: '@timestamp' + type: date + description: > + Event timestamp. diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/manifest.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/manifest.yml new file mode 100644 index 0000000000000..17c33c745ce74 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/data_stream/test/manifest.yml @@ -0,0 +1,3 @@ +title: Test Dataset + +type: logs diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/docs/README.md b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/docs/README.md new file mode 100644 index 0000000000000..0002afd9cdfc0 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/docs/README.md @@ -0,0 +1,3 @@ +# Test package + +For testing a prerelease package diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/img/logo_prerelease_64_color.svg b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/img/logo_prerelease_64_color.svg new file mode 100644 index 0000000000000..b03007a76ffcc --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/img/logo_prerelease_64_color.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/manifest.yml b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/manifest.yml new file mode 100644 index 0000000000000..1bc273ccaa4a3 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/prerelease/1.0.1-next/manifest.yml @@ -0,0 +1,21 @@ +format_version: 1.0.0 +name: prerelease +title: Prerelease package +description: This is a test package for testing that parsing a prerelease version works +version: 1.0.1-next +categories: ['security'] +type: integration +license: basic +owner: + github: elastic/fleet + +requirement: + elasticsearch: + versions: '>7.7.0' + kibana: + versions: '>7.7.0' + +icons: + - src: '/img/logo_prerelease_64_color.svg' + size: '16x16' + type: 'image/svg+xml' From 5227d822affdfa693133cefeed88b7f7e55f6d97 Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Thu, 9 Feb 2023 10:21:02 -0600 Subject: [PATCH 039/203] [Enterprise Search] Engines refinements (#150648) ## Summary - Per design removed the delete engine action from the engine indices page - Added the fields count link to schema page back since the schema page merged - Added usage of `FormattedPlural` for the engines indices table to render `1 index` instead of `1 indices` ### Screenshots Engines table, updated indices formatting ![image](https://user-images.githubusercontent.com/1972968/217668138-75771a8f-7033-4c16-9d56-8dc1a8c9ac07.png) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/engine/engine_indices.tsx | 35 ++++++------------- .../components/engine/engine_overview.tsx | 34 +++++++++++------- .../components/tables/engines_table.tsx | 6 ++-- 3 files changed, 34 insertions(+), 41 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_indices.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_indices.tsx index 745a6ed5e131e..823d234964408 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_indices.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_indices.tsx @@ -14,8 +14,6 @@ import { EuiBasicTableColumn, EuiButton, EuiConfirmModal, - EuiFlexGroup, - EuiFlexItem, EuiIcon, EuiInMemoryTable, EuiText, @@ -39,7 +37,6 @@ import { EnterpriseSearchEnginesPageTemplate } from '../layout/engines_page_temp import { AddIndicesFlyout } from './add_indices_flyout'; import { EngineIndicesLogic } from './engine_indices_logic'; -import { EngineViewHeaderActions } from './engine_view_header_actions'; export const EngineIndices: React.FC = () => { const { sendEnterpriseSearchTelemetry } = useActions(TelemetryLogic); @@ -184,27 +181,17 @@ export const EngineIndices: React.FC = () => { defaultMessage: 'Indices', }), rightSideItems: [ - - - - {i18n.translate( - 'xpack.enterpriseSearch.content.engine.indices.addNewIndicesButton', - { - defaultMessage: 'Add new indices', - } - )} - - - - - - , + + {i18n.translate('xpack.enterpriseSearch.content.engine.indices.addNewIndicesButton', { + defaultMessage: 'Add new indices', + })} + , ], }} engineName={engineName} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_overview.tsx index 20e60db46db80..83312c8290e21 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_overview.tsx @@ -79,19 +79,27 @@ export const EngineOverview: React.FC = () => { - - - - + + + + + + diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/components/tables/engines_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/components/tables/engines_table.tsx index 017564343f11e..c2c7eafc981b7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/components/tables/engines_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engines/components/tables/engines_table.tsx @@ -100,10 +100,8 @@ export const EnginesListTable: React.FC = ({ > ), From 932e58d3860a4e5584a9dc1c11ea3c174f6cf7f7 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Thu, 9 Feb 2023 18:42:27 +0200 Subject: [PATCH 040/203] [Lens] Fixes partition charts with 2 groups and multiterms on the second group (#150662) ## Summary Closes https://github.com/elastic/kibana/issues/150578 Fixes the bug that is described on the issue. The bug happens when you can more than 1 group and the last group has multiterms aggregation. At this case the values from the first group (terms) are not multiKeys so it fails. image ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../search/aggs/utils/get_aggs_formats.test.ts | 16 ++++++++++++++++ .../common/search/aggs/utils/get_aggs_formats.ts | 8 +++++--- 2 files changed, 21 insertions(+), 3 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 eb0d6df57b278..af366abeb5ee4 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 @@ -168,4 +168,20 @@ describe('getAggsFormats', () => { expect(format.convert(new MultiFieldKey({ key: terms }))).toBe('source - geo.src - geo.dest'); expect(getFormat).toHaveBeenCalledTimes(terms.length); }); + + test('not fails for non multiField Key values', () => { + const terms = ['source', 'geo.src', 'geo.dest']; + const mapping = { + id: 'multi_terms', + params: { + paramsPerField: [{ id: 'terms' }, { id: 'terms' }, { id: 'terms' }], + separator: ' - ', + }, + }; + + const format = getAggFormat(mapping, getFormat); + + expect(format.convert('text')).toBe(''); + expect(getFormat).toHaveBeenCalledTimes(terms.length); + }); }); 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 f9b8dd508d4a9..24312060147cb 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 @@ -164,9 +164,11 @@ export function getAggsFormats(getFieldFormat: GetFieldFormat): FieldFormatInsta const joinTemplate = `${params.separator ?? ' › '}`; - return (val as MultiFieldKey).keys - .map((valPart, i) => formats[i].convert(valPart, type)) - .join(joinTemplate); + return ( + (val as MultiFieldKey)?.keys + ?.map((valPart, i) => formats[i].convert(valPart, type)) + .join(joinTemplate) ?? '' + ); }; getConverterFor = (type: FieldFormatsContentType) => (val: string) => this.convert(val, type); }, From 59468bc435c28d1b3fe95b14b708b3f17c4cbac0 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:54:50 -0500 Subject: [PATCH 041/203] skip failing test suite (#150343) --- .../test/fleet_api_integration/apis/epm/install_prerelease.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts index 714d53513ba4d..928a168cc9042 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_prerelease.ts @@ -22,7 +22,8 @@ export default function (providerContext: FtrProviderContext) { await supertest.delete(`/api/fleet/epm/packages/${pkg}/${version}`).set('kbn-xsrf', 'xxxx'); }; - describe('installs package that has a prerelease version', async () => { + // Failing: See https://github.com/elastic/kibana/issues/150343 + describe.skip('installs package that has a prerelease version', async () => { skipIfNoDockerRegistry(providerContext); setupFleetAndAgents(providerContext); From b5dde1fcf5f54479906542a178cb87c616c7cb4f Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Thu, 9 Feb 2023 18:02:53 +0100 Subject: [PATCH 042/203] [Defend Workflows] Fix: proper regexp test for dynamic parameters presence (#150696) --- .../schedule_notification_response_actions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts index 238f06a3d4b59..2640679a7535d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts @@ -52,7 +52,7 @@ export const scheduleNotificationResponseActions = ( ? responseAction.params.queries : [{ query: responseAction.params.query }]; const containsDynamicQueries = some(temporaryQueries, (query) => { - return query.query ? CONTAINS_DYNAMIC_PARAMETER_REGEX.test(query.query) : false; + return query.query ? new RegExp(CONTAINS_DYNAMIC_PARAMETER_REGEX).test(query.query) : false; }); const { savedQueryId, packId, queries, ecsMapping, ...rest } = responseAction.params; From 6e06452aac11ed22efa923284fbb9ad4da1f7ce1 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Thu, 9 Feb 2023 17:16:35 +0000 Subject: [PATCH 043/203] [Fleet] Run agent policy schema in batches during fleet setup + add `xpack.fleet.setup.agentPolicySchemaUpgradeBatchSize` config (#150688) ## Summary Closes #150538 As part of the Fleet plugin setup, we check to see if any agent policies have an out of date `schema_version` and upgrade them. We encountered an error when this upgrade happens on a large number of agent policies as we attempted the upgrade in one large batch. This pull request performs the schema upgrade in batches of 100 by default and also adds the config value `xpack.fleet.setup.agentPolicySchemaUpgradeBatchSize` to make the batch size configurable. I have also added more debug logging to show progress, and reduced the response payload of one of our requests which was very large. ### Dev testing To test this you need an environemnt with lots of agent policies (> 2k) where `schema_version` is not set. To create an environment with a large number of agent policies I have added a new param to the agent creation script, I ran: ``` cd x-pack/plugins/fleet node scripts/create_agents --count 20 --kibana http://127.0.0.1:5601/mark --status online --delete --batches 3000 --concurrentBatches 100 ``` To generate 3000 agent policies each with 20 agents in. I then modified the agent policies so that they require an upgrade, as `system_indices_superuser` run: ``` POST /.kibana/_update_by_query { "query": { "bool": { "filter": [ { "term": { "type": "ingest-agent-policies" } } ] } }, "script": { "source": "ctx._source['ingest-agent-policies'].remove('schema_version')", "lang": "painless" } } ``` restarting kibana will run the setup and in batches. --- x-pack/plugins/fleet/common/types/index.ts | 3 ++ .../scripts/create_agents/create_agents.ts | 53 +++++++++++++------ x-pack/plugins/fleet/server/config.ts | 5 ++ .../fleet/server/services/agent_policy.ts | 10 +++- .../upgrade_agent_policy_schema_version.ts | 22 ++++++-- 5 files changed, 72 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/index.ts b/x-pack/plugins/fleet/common/types/index.ts index f819705b02230..202dd0c81ead5 100644 --- a/x-pack/plugins/fleet/common/types/index.ts +++ b/x-pack/plugins/fleet/common/types/index.ts @@ -36,6 +36,9 @@ export interface FleetConfigType { packageVerification?: { gpgKeyPath?: string; }; + setup?: { + agentPolicySchemaUpgradeBatchSize?: number; + }; developer?: { disableRegistryVersionCheck?: boolean; bundledPackageLocation?: string; diff --git a/x-pack/plugins/fleet/scripts/create_agents/create_agents.ts b/x-pack/plugins/fleet/scripts/create_agents/create_agents.ts index 4b47b56d9a48d..683d45a03757c 100644 --- a/x-pack/plugins/fleet/scripts/create_agents/create_agents.ts +++ b/x-pack/plugins/fleet/scripts/create_agents/create_agents.ts @@ -25,6 +25,8 @@ const printUsage = () => [--kibana]: full url of kibana instance to create agents and policy in e.g http://localhost:5601/mybase, defaults to http://localhost:5601 [--username]: username for kibana, defaults to elastic [--password]: password for kibana, defaults to changeme + [--batches]: run the script in batches, defaults to 1 e.g if count is 50 and batches is 10, 500 agents will be created and 10 agent policies + [--concurrentBatches]: how many batches to run concurrently, defaults to 10 `); const DEFAULT_KIBANA_URL = 'http://localhost:5601'; @@ -49,6 +51,8 @@ const { agentVersion: agentVersionArg, username: kbnUsername = DEFAULT_KIBANA_USERNAME, password: kbnPassword = DEFAULT_KIBANA_PASSWORD, + batches: batchesArg, + concurrentBatches: concurrentBatchesArg = 10, // ignore yargs positional args, we only care about named args _, $0, @@ -59,6 +63,8 @@ const statusesArg = (statusArg as string).split(',') as AgentStatus[]; const inactivityTimeout = inactivityTimeoutArg ? Number(inactivityTimeoutArg).valueOf() : DEFAULT_UNENROLL_TIMEOUT; +const batches = inactivityTimeoutArg ? Number(batchesArg).valueOf() : 1; +const concurrentBatches = concurrentBatchesArg ? Number(concurrentBatchesArg).valueOf() : 10; const count = countArg ? Number(countArg).valueOf() : DEFAULT_AGENT_COUNT; const kbnAuth = 'Basic ' + Buffer.from(kbnUsername + ':' + kbnPassword).toString('base64'); @@ -258,7 +264,7 @@ async function createAgentPolicy(id: string) { name: id, namespace: 'default', description: '', - monitoring_enabled: ['logs'], + monitoring_enabled: ['logs', 'metrics'], inactivity_timeout: inactivityTimeout, }), headers: { @@ -314,23 +320,40 @@ export async function run() { logger.info(`Deleted ${deleteRes.deleted} agents, took ${deleteRes.took}ms`); } - logger.info('Creating agent policy'); - - const agentPolicyId = 'script-create-agent-' + uuidv4(); - 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(`Role "${ES_SUPERUSER}" ${role.role.created ? 'created' : 'already exists'}`); logger.info(`User "${ES_SUPERUSER}" ${user.created ? 'created' : 'already exists'}`); - logger.info('Creating agent documents'); - const statusMap = statusesArg.reduce((acc, status) => ({ ...acc, [status]: count }), {}); - logStatusMap(statusMap); - const agents = createAgentsWithStatuses(statusMap, agentPolicyId, agentVersion); - const createRes = await createAgentDocsBulk(agents); - logger.info( - `Created ${createRes.items.length} agent docs, took ${createRes.took}, errors: ${createRes.errors}` - ); + let batchesRemaining = batches; + let totalAgents = 0; + while (batchesRemaining > 0) { + const currentBatchSize = Math.min(concurrentBatches, batchesRemaining); + if (batches > 1) { + logger.info(`Running ${currentBatchSize} batches. ${batchesRemaining} batches remaining`); + } + + await Promise.all( + Array(currentBatchSize) + .fill(0) + .map(async (__, i) => { + const agentPolicyId = 'script-create-agent-' + uuidv4(); + const agentPolicy = await createAgentPolicy(agentPolicyId); + logger.info(`Created agent policy ${agentPolicy.item.id}`); + + const statusMap = statusesArg.reduce((acc, status) => ({ ...acc, [status]: count }), {}); + logStatusMap(statusMap); + const agents = createAgentsWithStatuses(statusMap, agentPolicyId, agentVersion); + const createRes = await createAgentDocsBulk(agents); + logger.info( + `Batch complete, created ${createRes.items.length} agent docs, took ${createRes.took}, errors: ${createRes.errors}` + ); + totalAgents += createRes.items.length; + }) + ); + + batchesRemaining -= currentBatchSize; + } + + logger.info(`All batches complete. Created ${totalAgents} agents in total. Goodbye!`); } diff --git a/x-pack/plugins/fleet/server/config.ts b/x-pack/plugins/fleet/server/config.ts index 3c982ef9b516b..6cbbbd3a94bfe 100644 --- a/x-pack/plugins/fleet/server/config.ts +++ b/x-pack/plugins/fleet/server/config.ts @@ -120,6 +120,11 @@ export const config: PluginConfigDescriptor = { fleetServerHosts: PreconfiguredFleetServerHostsSchema, proxies: PreconfiguredFleetProxiesSchema, agentIdVerificationEnabled: schema.boolean({ defaultValue: true }), + setup: schema.maybe( + schema.object({ + agentPolicySchemaUpgradeBatchSize: schema.maybe(schema.number()), + }) + ), developer: schema.object({ disableRegistryVersionCheck: schema.boolean({ defaultValue: false }), allowAgentUpgradeSourceUri: schema.boolean({ defaultValue: false }), diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index d845d466ea381..5912e022370de 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -315,8 +315,14 @@ class AgentPolicyService { soClient: SavedObjectsClientContract, options: ListWithKuery & { withPackagePolicies?: boolean; + fields?: string[]; } - ): Promise<{ items: AgentPolicy[]; total: number; page: number; perPage: number }> { + ): Promise<{ + items: AgentPolicy[]; + total: number; + page: number; + perPage: number; + }> { const { page = 1, perPage = 20, @@ -324,6 +330,7 @@ class AgentPolicyService { sortOrder = 'desc', kuery, withPackagePolicies = false, + fields, } = options; const baseFindParams = { @@ -332,6 +339,7 @@ class AgentPolicyService { sortOrder, page, perPage, + ...(fields ? { fields } : {}), }; const filter = kuery ? normalizeKuery(SAVED_OBJECT_TYPE, kuery) : undefined; let agentPoliciesSO; diff --git a/x-pack/plugins/fleet/server/services/setup/upgrade_agent_policy_schema_version.ts b/x-pack/plugins/fleet/server/services/setup/upgrade_agent_policy_schema_version.ts index a02c81c2cfab1..0dfe1227af050 100644 --- a/x-pack/plugins/fleet/server/services/setup/upgrade_agent_policy_schema_version.ts +++ b/x-pack/plugins/fleet/server/services/setup/upgrade_agent_policy_schema_version.ts @@ -10,14 +10,16 @@ import type { SavedObjectsClientContract } from '@kbn/core/server'; import { AGENT_POLICY_SAVED_OBJECT_TYPE, FLEET_AGENT_POLICIES_SCHEMA_VERSION, - SO_SEARCH_LIMIT, } from '../../constants'; import { agentPolicyService } from '../agent_policy'; +import { appContextService } from '../app_context'; -function getOutdatedAgentPoliciesBatch(soClient: SavedObjectsClientContract) { +const DEFAULT_BATCH_SIZE = 100; +function getOutdatedAgentPoliciesBatch(soClient: SavedObjectsClientContract, batchSize: number) { return agentPolicyService.list(soClient, { - perPage: SO_SEARCH_LIMIT, + perPage: batchSize, kuery: `NOT ${AGENT_POLICY_SAVED_OBJECT_TYPE}.schema_version:${FLEET_AGENT_POLICIES_SCHEMA_VERSION}`, + fields: ['id'], // we only need the ID of the agent policy }); } @@ -26,13 +28,23 @@ function getOutdatedAgentPoliciesBatch(soClient: SavedObjectsClientContract) { // deploy outdated policies to .fleet-policies index // bump oudated SOs schema_version export async function upgradeAgentPolicySchemaVersion(soClient: SavedObjectsClientContract) { - let outdatedAgentPolicies = await getOutdatedAgentPoliciesBatch(soClient); + const config = appContextService.getConfig(); + const logger = appContextService.getLogger(); + const batchSize = config?.setup?.agentPolicySchemaUpgradeBatchSize ?? DEFAULT_BATCH_SIZE; + let outdatedAgentPolicies = await getOutdatedAgentPoliciesBatch(soClient, batchSize); + logger.debug(`Found ${outdatedAgentPolicies.total} outdated agent policies`); while (outdatedAgentPolicies.total > 0) { + const start = Date.now(); const outdatedAgentPolicyIds = outdatedAgentPolicies.items.map( (outdatedAgentPolicy) => outdatedAgentPolicy.id ); await agentPolicyService.deployPolicies(soClient, outdatedAgentPolicyIds); - outdatedAgentPolicies = await getOutdatedAgentPoliciesBatch(soClient); + outdatedAgentPolicies = await getOutdatedAgentPoliciesBatch(soClient, batchSize); + logger.debug( + `Upgraded ${outdatedAgentPolicyIds.length} agent policies in ${Date.now() - start}ms, ${ + outdatedAgentPolicies.total + } remaining` + ); } } From 3faf6f519c595c824056bb2a146160e77f3813a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Thu, 9 Feb 2023 18:37:48 +0100 Subject: [PATCH 044/203] [CODEOWNERS] Skip review on changes to translation files (#150678) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 3 +++ packages/kbn-generate/src/commands/codeowners_command.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0491048bcf81b..4feac718f908d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1191,3 +1191,6 @@ packages/kbn-yarn-lock-validator @elastic/kibana-operations # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design + +# Changes to translation files should not ping code reviewers +x-pack/plugins/translations/translations diff --git a/packages/kbn-generate/src/commands/codeowners_command.ts b/packages/kbn-generate/src/commands/codeowners_command.ts index 733e123815dce..ed3f51d5bc087 100644 --- a/packages/kbn-generate/src/commands/codeowners_command.ts +++ b/packages/kbn-generate/src/commands/codeowners_command.ts @@ -30,6 +30,9 @@ const GENERATED_TRAILER = ` # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design + +# Changes to translation files should not ping code reviewers +x-pack/plugins/translations/translations `; function normalizeDir(dirish: string): string { From cb17912b6c96ffeb1f2934ede98caf0782127a4b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 9 Feb 2023 10:38:34 -0700 Subject: [PATCH 045/203] =?UTF-8?q?fix=20flaky=20test=20x-pack/test/functi?= =?UTF-8?q?onal/apps/dashboard/group2/panel=5Ftime=5Frange=C2=B7ts=20(#150?= =?UTF-8?q?630)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixers https://github.com/elastic/kibana/issues/150490 flaky test runner https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1899 Failures caused by settings panel not closing. PR resolves issue by dismissing toasts so save button is clickable and retrying if settings panel does not close. Screen Shot 2023-02-08 at 12 30 19 PM --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../functional/services/dashboard/panel_settings.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/functional/services/dashboard/panel_settings.ts b/test/functional/services/dashboard/panel_settings.ts index d82dabf097eb7..a90a51fdc2feb 100644 --- a/test/functional/services/dashboard/panel_settings.ts +++ b/test/functional/services/dashboard/panel_settings.ts @@ -11,6 +11,8 @@ import { CommonlyUsed } from '../../page_objects/time_picker'; export function DashboardCustomizePanelProvider({ getService }: FtrProviderContext) { const log = getService('log'); + const retry = getService('retry'); + const toasts = getService('toasts'); const testSubjects = getService('testSubjects'); return new (class DashboardCustomizePanel { @@ -95,12 +97,19 @@ export function DashboardCustomizePanelProvider({ getService }: FtrProviderConte public async clickSaveButton() { log.debug('clickSaveButton'); - await testSubjects.click('saveCustomizePanelButton'); + await retry.try(async () => { + await toasts.dismissAllToasts(); + await testSubjects.click('saveCustomizePanelButton'); + await testSubjects.waitForDeleted('saveCustomizePanelButton'); + }); } public async clickCancelButton() { log.debug('clickCancelButton'); - await testSubjects.click('cancelCustomizePanelButton'); + await retry.try(async () => { + await testSubjects.click('cancelCustomizePanelButton'); + await testSubjects.waitForDeleted('cancelCustomizePanelButton'); + }); } public async clickToggleShowCustomTimeRange() { From c80f8b426b7b0bf10b726e7b3e264b8f0e628c6e Mon Sep 17 00:00:00 2001 From: Lola Date: Thu, 9 Feb 2023 13:04:08 -0500 Subject: [PATCH 046/203] [Cloud Posture][Dashboard] dashboard re-design enhancements (#150394) ## Summary [Issue 5676](https://github.com/elastic/security-team/issues/5676) Summarize your PR. If it involves visual changes include a screenshot or gif. image I address 1. Column misalignment which compact components need additional padding image image 2. Capitalize Stats text image 3. Remove the Line in the second Risk table` Won't do image 4. Align text with chart data image image 5. Align the Benchmark section content image --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/components/chart_panel.tsx | 4 +++- .../public/components/csp_counter_card.tsx | 3 +++ .../cloud_posture_score_chart.tsx | 8 +++++++- .../compliance_charts/risks_table.tsx | 14 ++++++++++++++ .../dashboard_sections/benchmarks_section.tsx | 3 +++ 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx b/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx index 01291b287293a..c7772063b2f90 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx @@ -13,6 +13,7 @@ import { EuiLoadingChart, EuiFlexGroup, EuiFlexItem, + useEuiTheme, } from '@elastic/eui'; import { CHART_PANEL_TEST_SUBJECTS } from './test_subjects'; @@ -52,6 +53,7 @@ export const ChartPanel: React.FC = ({ isError, children, }) => { + const { euiTheme } = useEuiTheme(); const renderChart = () => { if (isLoading) return ; if (isError) return ; @@ -64,7 +66,7 @@ export const ChartPanel: React.FC = ({ {title && ( -

{title}

+

{title}

)} diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_counter_card.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_counter_card.tsx index 4b953d7030251..cb3d0c3527c57 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/csp_counter_card.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_counter_card.tsx @@ -44,6 +44,9 @@ export const CspCounterCard = (counter: CspCounterCardProps) => { display: 'flex', flexDirection: 'column', justifyContent: 'space-around', + '.euiText h6': { + textTransform: 'capitalize', + }, }} titleSize="s" title={counter.title} diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/cloud_posture_score_chart.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/cloud_posture_score_chart.tsx index 8eaf05374bf96..81bd0f3f6052c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/cloud_posture_score_chart.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/cloud_posture_score_chart.tsx @@ -53,7 +53,13 @@ const PercentageInfo = ({ const percentage = getPostureScorePercentage(postureScore); return ( - +

{percentage}

); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx index 51f7847ffe5a1..4f95992472ab6 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx @@ -15,6 +15,7 @@ import { EuiLink, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; import { ComplianceScoreBar } from '../../../components/compliance_score_bar'; import { ComplianceDashboardData, GroupedFindingsEvaluation } from '../../../../common/types'; @@ -84,6 +85,19 @@ export const RisksTable = ({ + className="risk-table" + css={ + compact + ? css` + thead { + display: none; + } + .euiTable .euiTableRow .euiTableRowCell { + border-top: none; + } + ` + : undefined + } items={sortedByComplianceScore} columns={columns} /> diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx index ba3f16dad46c9..adc112bfa57a5 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx @@ -173,6 +173,9 @@ export const BenchmarksSection = ({ Date: Thu, 9 Feb 2023 11:07:54 -0700 Subject: [PATCH 047/203] [Maps] fixes Kibana maps shows MVT borders if the geometry border style is greater than 1 (#150497) Fixes https://github.com/elastic/kibana/issues/150187 PR passes buffer to kibana MVT route which passes buffer to Elasticsearch vector tile API. Buffer is set based on line width style property. Screen Shot 2023-02-07 at 2 43 15 PM --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../maps/common/mvt_request_body.test.ts | 4 ++ .../plugins/maps/common/mvt_request_body.ts | 6 ++ .../layers/heatmap_layer/heatmap_layer.ts | 1 + .../mvt_vector_layer/mvt_source_data.test.ts | 61 +++++++++++++++++++ .../mvt_vector_layer/mvt_source_data.ts | 9 ++- .../mvt_vector_layer/mvt_vector_layer.tsx | 20 +++++- .../es_geo_grid_source.test.ts | 4 +- .../es_geo_grid_source/es_geo_grid_source.tsx | 4 +- .../es_search_source/es_search_source.test.ts | 4 +- .../es_search_source/es_search_source.tsx | 4 +- .../vector_source/mvt_vector_source.ts | 3 +- .../components/get_tile_request.test.ts | 6 +- .../components/get_tile_request.ts | 7 +++ x-pack/plugins/maps/server/mvt/mvt_routes.ts | 4 ++ .../apps/maps/group4/mvt_geotile_grid.js | 1 + .../apps/maps/group4/mvt_scaling.js | 1 + 16 files changed, 127 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/maps/common/mvt_request_body.test.ts b/x-pack/plugins/maps/common/mvt_request_body.test.ts index eef26cb526ad4..53861df768d85 100644 --- a/x-pack/plugins/maps/common/mvt_request_body.test.ts +++ b/x-pack/plugins/maps/common/mvt_request_body.test.ts @@ -93,6 +93,7 @@ describe('getAggsTileRequest', () => { query: {}, }; const { path } = getAggsTileRequest({ + buffer: 5, encodedRequestBody: encodeMvtResponseBody(searchRequest), geometryFieldName: 'my location', gridPrecision: 8, @@ -115,6 +116,7 @@ describe('getHitsTileRequest', () => { query: {}, }; const { path } = getHitsTileRequest({ + buffer: 5, encodedRequestBody: encodeMvtResponseBody(searchRequest), geometryFieldName: 'my location', hasLabels: true, @@ -135,6 +137,7 @@ describe('getHitsTileRequest', () => { sort: ['timestamp'], }; const { body } = getHitsTileRequest({ + buffer: 5, encodedRequestBody: encodeMvtResponseBody(searchRequest), geometryFieldName: 'my location', hasLabels: true, @@ -153,6 +156,7 @@ describe('getHitsTileRequest', () => { query: {}, }; const { body } = getHitsTileRequest({ + buffer: 5, encodedRequestBody: encodeMvtResponseBody(searchRequest), geometryFieldName: 'my location', hasLabels: true, diff --git a/x-pack/plugins/maps/common/mvt_request_body.ts b/x-pack/plugins/maps/common/mvt_request_body.ts index 72b78786e5046..2617a668f4ebd 100644 --- a/x-pack/plugins/maps/common/mvt_request_body.ts +++ b/x-pack/plugins/maps/common/mvt_request_body.ts @@ -24,6 +24,7 @@ export function encodeMvtResponseBody(unencodedRequestBody: estypes.SearchReques } export function getAggsTileRequest({ + buffer, encodedRequestBody, geometryFieldName, gridPrecision, @@ -34,6 +35,7 @@ export function getAggsTileRequest({ y, z, }: { + buffer: number; encodedRequestBody: string; geometryFieldName: string; gridPrecision: number; @@ -53,6 +55,7 @@ export function getAggsTileRequest({ geometryFieldName )}/${z}/${x}/${y}`, body: { + buffer, size: 0, // no hits grid_precision: gridPrecision, exact_bounds: false, @@ -69,6 +72,7 @@ export function getAggsTileRequest({ } export function getHitsTileRequest({ + buffer, encodedRequestBody, geometryFieldName, hasLabels, @@ -77,6 +81,7 @@ export function getHitsTileRequest({ y, z, }: { + buffer: number; encodedRequestBody: string; geometryFieldName: string; hasLabels: boolean; @@ -90,6 +95,7 @@ export function getHitsTileRequest({ throw new Error('Required requestBody parameter not provided'); } const tileRequestBody = { + buffer, grid_precision: 0, // no aggs exact_bounds: true, extent: 4096, // full resolution, diff --git a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts index bc013cb958a4f..0d9f11dbe0646 100644 --- a/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/heatmap_layer/heatmap_layer.ts @@ -87,6 +87,7 @@ export class HeatmapLayer extends AbstractLayer { async syncData(syncContext: DataRequestContext) { await syncMvtSourceData({ + buffer: 0, hasLabels: false, layerId: this.getId(), layerName: await this.getDisplayName(), diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.test.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.test.ts index 74c9f74c9d2ec..d67d9ade54625 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.test.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.test.ts @@ -50,6 +50,7 @@ describe('syncMvtSourceData', () => { const syncContext = new MockSyncContext({ dataFilters: {} }); await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', @@ -82,6 +83,7 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf', refreshToken: '12345', hasLabels: false, + buffer: 5, }); }); @@ -99,6 +101,7 @@ describe('syncMvtSourceData', () => { }; await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', @@ -114,6 +117,7 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', refreshToken: '12345', hasLabels: false, + buffer: 5, }; }, } as unknown as DataRequest, @@ -144,6 +148,7 @@ describe('syncMvtSourceData', () => { }; await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', @@ -159,6 +164,7 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', refreshToken: '12345', hasLabels: false, + buffer: 5, }; }, } as unknown as DataRequest, @@ -186,6 +192,7 @@ describe('syncMvtSourceData', () => { }; await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', @@ -201,6 +208,7 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', refreshToken: '12345', hasLabels: false, + buffer: 5, }; }, } as unknown as DataRequest, @@ -236,6 +244,7 @@ describe('syncMvtSourceData', () => { }; await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', @@ -251,6 +260,7 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', refreshToken: '12345', hasLabels: false, + buffer: 5, }; }, } as unknown as DataRequest, @@ -278,6 +288,7 @@ describe('syncMvtSourceData', () => { }; await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', @@ -293,6 +304,7 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', refreshToken: '12345', hasLabels: false, + buffer: 5, }; }, } as unknown as DataRequest, @@ -320,6 +332,7 @@ describe('syncMvtSourceData', () => { }; await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', @@ -335,6 +348,7 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', refreshToken: '12345', hasLabels: false, + buffer: 5, }; }, } as unknown as DataRequest, @@ -362,6 +376,7 @@ describe('syncMvtSourceData', () => { }; await syncMvtSourceData({ + buffer: 5, hasLabels: true, layerId: 'layer1', layerName: 'my layer', @@ -377,6 +392,51 @@ describe('syncMvtSourceData', () => { tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', refreshToken: '12345', hasLabels: false, + buffer: 5, + }; + }, + } as unknown as DataRequest, + requestMeta: { ...prevRequestMeta }, + source: mockSource, + syncContext, + }); + // @ts-expect-error + sinon.assert.calledOnce(syncContext.startLoading); + // @ts-expect-error + sinon.assert.calledOnce(syncContext.stopLoading); + }); + + test('Should re-sync when buffer state changes', async () => { + const syncContext = new MockSyncContext({ dataFilters: {} }); + const prevRequestMeta = { + ...syncContext.dataFilters, + applyGlobalQuery: true, + applyGlobalTime: true, + applyForceRefresh: true, + fieldNames: [], + sourceMeta: {}, + isForceRefresh: false, + isFeatureEditorOpenForLayer: false, + }; + + await syncMvtSourceData({ + buffer: 5, + hasLabels: false, + layerId: 'layer1', + layerName: 'my layer', + prevDataRequest: { + getMeta: () => { + return prevRequestMeta; + }, + getData: () => { + return { + tileMinZoom: 4, + tileMaxZoom: 14, + tileSourceLayer: 'aggs', + tileUrl: 'https://example.com/{x}/{y}/{z}.pbf?token=12345', + refreshToken: '12345', + hasLabels: false, + buffer: 7, }; }, } as unknown as DataRequest, @@ -394,6 +454,7 @@ describe('syncMvtSourceData', () => { const syncContext = new MockSyncContext({ dataFilters: {} }); await syncMvtSourceData({ + buffer: 5, hasLabels: false, layerId: 'layer1', layerName: 'my layer', diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts index a3cfdabf17249..17a92fff97ff7 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_source_data.ts @@ -21,9 +21,11 @@ export interface MvtSourceData { tileUrl: string; refreshToken: string; hasLabels: boolean; + buffer: number; } export async function syncMvtSourceData({ + buffer, hasLabels, layerId, layerName, @@ -32,6 +34,7 @@ export async function syncMvtSourceData({ source, syncContext, }: { + buffer: number; hasLabels: boolean; layerId: string; layerName: string; @@ -62,7 +65,8 @@ export async function syncMvtSourceData({ !syncContext.forceRefreshDueToDrawing && noChangesInSourceState && noChangesInSearchState && - prevData.hasLabels === hasLabels; + prevData.hasLabels === hasLabels && + prevData.buffer === buffer; if (canSkip) { return; @@ -78,7 +82,7 @@ export async function syncMvtSourceData({ ? uuidv4() : prevData.refreshToken; - const tileUrl = await source.getTileUrl(requestMeta, refreshToken, hasLabels); + const tileUrl = await source.getTileUrl(requestMeta, refreshToken, hasLabels, buffer); if (source.isESSource()) { syncContext.inspectorAdapters.vectorTiles.addLayer(layerId, layerName, tileUrl); } @@ -89,6 +93,7 @@ export async function syncMvtSourceData({ tileMaxZoom: source.getMaxZoom(), refreshToken, hasLabels, + buffer, }; syncContext.stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, sourceData, {}); } catch (error) { diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx index a16093af20426..398d3daeae28e 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/mvt_vector_layer/mvt_vector_layer.tsx @@ -17,8 +17,10 @@ import { Feature } from 'geojson'; import { i18n } from '@kbn/i18n'; import { buildPhrasesFilter } from '@kbn/es-query'; import { VectorStyle } from '../../../styles/vector/vector_style'; +import type { DynamicSizeProperty } from '../../../styles/vector/properties/dynamic_size_property'; +import type { StaticSizeProperty } from '../../../styles/vector/properties/static_size_property'; import { getField } from '../../../../../common/elasticsearch_util'; -import { LAYER_TYPE, SOURCE_TYPES } from '../../../../../common/constants'; +import { LAYER_TYPE, SOURCE_TYPES, VECTOR_STYLES } from '../../../../../common/constants'; import { NO_RESULTS_ICON_AND_TOOLTIPCONTENT, AbstractVectorLayer, @@ -225,7 +227,23 @@ export class MvtVectorLayer extends AbstractVectorLayer { await this._syncSourceFormatters(syncContext, this.getSource(), this.getCurrentStyle()); await this._syncSupportsFeatureEditing({ syncContext, source: this.getSource() }); + let maxLineWidth = 0; + const lineWidth = this.getCurrentStyle() + .getAllStyleProperties() + .find((styleProperty) => { + return styleProperty.getStyleName() === VECTOR_STYLES.LINE_WIDTH; + }); + if (lineWidth) { + if (!lineWidth.isDynamic() && lineWidth.isComplete()) { + maxLineWidth = (lineWidth as StaticSizeProperty).getOptions().size; + } else if (lineWidth.isDynamic() && lineWidth.isComplete()) { + maxLineWidth = (lineWidth as DynamicSizeProperty).getOptions().maxSize; + } + } + const buffer = Math.ceil(3.5 * maxLineWidth); + await syncMvtSourceData({ + buffer, hasLabels: this.getCurrentStyle().hasLabels(), layerId: this.getId(), layerName: await this.getDisplayName(), diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts index 6d6ff971e7067..a7d0b4c9beb8f 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -308,10 +308,10 @@ describe('ESGeoGridSource', () => { }); it('getTileUrl', async () => { - const tileUrl = await mvtGeogridSource.getTileUrl(vectorSourceRequestMeta, '1234', false); + const tileUrl = await mvtGeogridSource.getTileUrl(vectorSourceRequestMeta, '1234', false, 5); expect(tileUrl).toEqual( - "rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foo-*&gridPrecision=8&hasLabels=false&requestBody=(foobar%3AES_DSL_PLACEHOLDER%2Cparams%3A('0'%3A('0'%3Aindex%2C'1'%3A(fields%3A()))%2C'1'%3A('0'%3Asize%2C'1'%3A0)%2C'2'%3A('0'%3Afilter%2C'1'%3A!())%2C'3'%3A('0'%3Aquery)%2C'4'%3A('0'%3Aindex%2C'1'%3A(fields%3A()))%2C'5'%3A('0'%3Aquery%2C'1'%3A(language%3AKQL%2Cquery%3A''))%2C'6'%3A('0'%3Aaggs%2C'1'%3A())))&renderAs=heatmap&token=1234" + "rootdir/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foo-*&gridPrecision=8&hasLabels=false&buffer=5&requestBody=(foobar%3AES_DSL_PLACEHOLDER%2Cparams%3A('0'%3A('0'%3Aindex%2C'1'%3A(fields%3A()))%2C'1'%3A('0'%3Asize%2C'1'%3A0)%2C'2'%3A('0'%3Afilter%2C'1'%3A!())%2C'3'%3A('0'%3Aquery)%2C'4'%3A('0'%3Aindex%2C'1'%3A(fields%3A()))%2C'5'%3A('0'%3Aquery%2C'1'%3A(language%3AKQL%2Cquery%3A''))%2C'6'%3A('0'%3Aaggs%2C'1'%3A())))&renderAs=heatmap&token=1234" ); }); }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx index 314a2f1205bda..7102978602e90 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx @@ -502,7 +502,8 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo async getTileUrl( searchFilters: VectorSourceRequestMeta, refreshToken: string, - hasLabels: boolean + hasLabels: boolean, + buffer: number ): Promise { const dataView = await this.getIndexPattern(); const searchSource = await this.makeSearchSource(searchFilters, 0); @@ -517,6 +518,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo &index=${dataView.getIndexPattern()}\ &gridPrecision=${this._getGeoGridPrecisionResolutionDelta()}\ &hasLabels=${hasLabels}\ +&buffer=${buffer}\ &requestBody=${encodeMvtResponseBody(searchSource.getSearchRequestBody())}\ &renderAs=${this._descriptor.requestType}\ &token=${refreshToken}`; diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts index 3d41082dcdf73..2e9fa9e027f5a 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.test.ts @@ -115,9 +115,9 @@ describe('ESSearchSource', () => { geoField: geoFieldName, indexPatternId: 'ipId', }); - const tileUrl = await esSearchSource.getTileUrl(searchFilters, '1234', false); + const tileUrl = await esSearchSource.getTileUrl(searchFilters, '1234', false, 5); expect(tileUrl).toBe( - `rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&hasLabels=false&requestBody=(foobar%3AES_DSL_PLACEHOLDER%2Cparams%3A('0'%3A('0'%3Aindex%2C'1'%3A(fields%3A()%2Ctitle%3A'foobar-title-*'))%2C'1'%3A('0'%3Asize%2C'1'%3A1000)%2C'2'%3A('0'%3Afilter%2C'1'%3A!())%2C'3'%3A('0'%3Aquery)%2C'4'%3A('0'%3Aindex%2C'1'%3A(fields%3A()%2Ctitle%3A'foobar-title-*'))%2C'5'%3A('0'%3Aquery%2C'1'%3A(language%3AKQL%2Cquery%3A'tooltipField%3A%20foobar'))%2C'6'%3A('0'%3AfieldsFromSource%2C'1'%3A!(_id))%2C'7'%3A('0'%3Asource%2C'1'%3A!f)%2C'8'%3A('0'%3Afields%2C'1'%3A!(tooltipField%2CstyleField))))&token=1234` + `rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=bar&index=foobar-title-*&hasLabels=false&buffer=5&requestBody=(foobar%3AES_DSL_PLACEHOLDER%2Cparams%3A('0'%3A('0'%3Aindex%2C'1'%3A(fields%3A()%2Ctitle%3A'foobar-title-*'))%2C'1'%3A('0'%3Asize%2C'1'%3A1000)%2C'2'%3A('0'%3Afilter%2C'1'%3A!())%2C'3'%3A('0'%3Aquery)%2C'4'%3A('0'%3Aindex%2C'1'%3A(fields%3A()%2Ctitle%3A'foobar-title-*'))%2C'5'%3A('0'%3Aquery%2C'1'%3A(language%3AKQL%2Cquery%3A'tooltipField%3A%20foobar'))%2C'6'%3A('0'%3AfieldsFromSource%2C'1'%3A!(_id))%2C'7'%3A('0'%3Asource%2C'1'%3A!f)%2C'8'%3A('0'%3Afields%2C'1'%3A!(tooltipField%2CstyleField))))&token=1234` ); }); }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx index ae639e9f2121d..c5ed07a4c0e18 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx @@ -824,7 +824,8 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource async getTileUrl( searchFilters: VectorSourceRequestMeta, refreshToken: string, - hasLabels: boolean + hasLabels: boolean, + buffer: number ): Promise { const dataView = await this.getIndexPattern(); const indexSettings = await loadIndexSettings(dataView.getIndexPattern()); @@ -872,6 +873,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource ?geometryFieldName=${this._descriptor.geoField}\ &index=${dataView.getIndexPattern()}\ &hasLabels=${hasLabels}\ +&buffer=${buffer}\ &requestBody=${encodeMvtResponseBody(requestBody)}\ &token=${refreshToken}`; } diff --git a/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts b/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts index c6f55436efc15..8842d96fdeb51 100644 --- a/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/vector_source/mvt_vector_source.ts @@ -16,7 +16,8 @@ export interface IMvtVectorSource extends IVectorSource { getTileUrl( searchFilters: VectorSourceRequestMeta, refreshToken: string, - hasLabels: boolean + hasLabels: boolean, + buffer: number ): Promise; /* diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts index d43366031eea3..91f9e02cd7c1c 100644 --- a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.test.ts @@ -11,7 +11,7 @@ test('Should return elasticsearch vector tile request for aggs tiles', () => { expect( getTileRequest({ layerId: '1', - tileUrl: `/pof/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=geo.coordinates&hasLabels=false&index=kibana_sample_data_logs&gridPrecision=8&requestBody=(_source%3A(excludes%3A!())%2Caggs%3A()%2Cfields%3A!((field%3A'%40timestamp'%2Cformat%3Adate_time)%2C(field%3Atimestamp%2Cformat%3Adate_time)%2C(field%3Autc_time%2Cformat%3Adate_time))%2Cquery%3A(bool%3A(filter%3A!((match_phrase%3A(machine.os.keyword%3Aios))%2C(range%3A(timestamp%3A(format%3Astrict_date_optional_time%2Cgte%3A'2022-04-22T16%3A46%3A00.744Z'%2Clte%3A'2022-04-29T16%3A46%3A05.345Z'))))%2Cmust%3A!()%2Cmust_not%3A!()%2Cshould%3A!()))%2Cruntime_mappings%3A(hour_of_day%3A(script%3A(source%3A'emit(doc%5B!'timestamp!'%5D.value.getHour())%3B')%2Ctype%3Along))%2Cscript_fields%3A()%2Csize%3A0%2Cstored_fields%3A!('*'))&renderAs=heatmap&token=e8bff005-ccea-464a-ae56-2061b4f8ce68`, + tileUrl: `/pof/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=geo.coordinates&hasLabels=false&buffer=7&index=kibana_sample_data_logs&gridPrecision=8&requestBody=(_source%3A(excludes%3A!())%2Caggs%3A()%2Cfields%3A!((field%3A'%40timestamp'%2Cformat%3Adate_time)%2C(field%3Atimestamp%2Cformat%3Adate_time)%2C(field%3Autc_time%2Cformat%3Adate_time))%2Cquery%3A(bool%3A(filter%3A!((match_phrase%3A(machine.os.keyword%3Aios))%2C(range%3A(timestamp%3A(format%3Astrict_date_optional_time%2Cgte%3A'2022-04-22T16%3A46%3A00.744Z'%2Clte%3A'2022-04-29T16%3A46%3A05.345Z'))))%2Cmust%3A!()%2Cmust_not%3A!()%2Cshould%3A!()))%2Cruntime_mappings%3A(hour_of_day%3A(script%3A(source%3A'emit(doc%5B!'timestamp!'%5D.value.getHour())%3B')%2Ctype%3Along))%2Cscript_fields%3A()%2Csize%3A0%2Cstored_fields%3A!('*'))&renderAs=heatmap&token=e8bff005-ccea-464a-ae56-2061b4f8ce68`, x: 3, y: 0, z: 2, @@ -19,6 +19,7 @@ test('Should return elasticsearch vector tile request for aggs tiles', () => { ).toEqual({ path: '/kibana_sample_data_logs/_mvt/geo.coordinates/2/3/0', body: { + buffer: 7, size: 0, grid_precision: 8, exact_bounds: false, @@ -80,7 +81,7 @@ test('Should return elasticsearch vector tile request for hits tiles', () => { expect( getTileRequest({ layerId: '1', - tileUrl: `http://localhost:5601/zuv/api/maps/mvt/getTile/4/2/6.pbf?geometryFieldName=geo.coordinates&index=kibana_sample_data_logs&hasLabels=true&requestBody=(_source%3A!f%2Cfields%3A!((field%3A%27%40timestamp%27%2Cformat%3Aepoch_millis)%2Cbytes)%2Cquery%3A(bool%3A(filter%3A!((range%3A(timestamp%3A(format%3Astrict_date_optional_time%2Cgte%3A%272022-06-15T20%3A00%3A00.000Z%27%2Clte%3A%272022-06-16T20%3A48%3A02.517Z%27))))%2Cmust%3A!()%2Cmust_not%3A!()%2Cshould%3A!()))%2Cruntime_mappings%3A(hour_of_day%3A(script%3A(source%3A%27emit(doc%5B!%27timestamp!%27%5D.value.getHour())%3B%27)%2Ctype%3Along))%2Csize%3A10000%2Csort%3A!((%27%40timestamp%27%3A(order%3Adesc%2Cunmapped_type%3Aboolean))))&token=7afe7c2d-c96b-4bdb-9b5e-819aceac80a1`, + tileUrl: `http://localhost:5601/zuv/api/maps/mvt/getTile/4/2/6.pbf?geometryFieldName=geo.coordinates&index=kibana_sample_data_logs&hasLabels=true&buffer=7&requestBody=(_source%3A!f%2Cfields%3A!((field%3A%27%40timestamp%27%2Cformat%3Aepoch_millis)%2Cbytes)%2Cquery%3A(bool%3A(filter%3A!((range%3A(timestamp%3A(format%3Astrict_date_optional_time%2Cgte%3A%272022-06-15T20%3A00%3A00.000Z%27%2Clte%3A%272022-06-16T20%3A48%3A02.517Z%27))))%2Cmust%3A!()%2Cmust_not%3A!()%2Cshould%3A!()))%2Cruntime_mappings%3A(hour_of_day%3A(script%3A(source%3A%27emit(doc%5B!%27timestamp!%27%5D.value.getHour())%3B%27)%2Ctype%3Along))%2Csize%3A10000%2Csort%3A!((%27%40timestamp%27%3A(order%3Adesc%2Cunmapped_type%3Aboolean))))&token=7afe7c2d-c96b-4bdb-9b5e-819aceac80a1`, x: 0, y: 0, z: 2, @@ -88,6 +89,7 @@ test('Should return elasticsearch vector tile request for hits tiles', () => { ).toEqual({ path: '/kibana_sample_data_logs/_mvt/geo.coordinates/2/0/0', body: { + buffer: 7, grid_precision: 0, exact_bounds: true, extent: 4096, diff --git a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.ts b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.ts index c79ef7c64fdd1..0002472608664 100644 --- a/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.ts +++ b/x-pack/plugins/maps/public/inspector/vector_tile_adapter/components/get_tile_request.ts @@ -39,8 +39,14 @@ export function getTileRequest(tileRequest: TileRequest): { path?: string; body? ? searchParams.get('hasLabels') === 'true' : false; + if (!searchParams.has('buffer')) { + throw new Error(`Required query parameter 'buffer' not provided.`); + } + const buffer = parseInt(searchParams.get('buffer') as string, 10); + if (tileRequest.tileUrl.includes(MVT_GETGRIDTILE_API_PATH)) { return getAggsTileRequest({ + buffer, encodedRequestBody, geometryFieldName, gridPrecision: parseInt(searchParams.get('gridPrecision') as string, 10), @@ -55,6 +61,7 @@ export function getTileRequest(tileRequest: TileRequest): { path?: string; body? if (tileRequest.tileUrl.includes(MVT_GETTILE_API_PATH)) { return getHitsTileRequest({ + buffer, encodedRequestBody, geometryFieldName, hasLabels, diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 96f6bafadabfd..4ed26677b6286 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -44,6 +44,7 @@ export function initMVTRoutes({ z: schema.number(), }), query: schema.object({ + buffer: schema.maybe(schema.number()), geometryFieldName: schema.string(), hasLabels: schema.boolean(), requestBody: schema.string(), @@ -68,6 +69,7 @@ export function initMVTRoutes({ }; try { tileRequest = getHitsTileRequest({ + buffer: 'buffer' in query ? parseInt(query.buffer, 10) : 5, encodedRequestBody: query.requestBody as string, geometryFieldName: query.geometryFieldName as string, hasLabels: query.hasLabels as boolean, @@ -107,6 +109,7 @@ export function initMVTRoutes({ z: schema.number(), }), query: schema.object({ + buffer: schema.maybe(schema.number()), geometryFieldName: schema.string(), hasLabels: schema.boolean(), requestBody: schema.string(), @@ -133,6 +136,7 @@ export function initMVTRoutes({ }; try { tileRequest = getAggsTileRequest({ + buffer: 'buffer' in query ? parseInt(query.buffer, 10) : 5, encodedRequestBody: query.requestBody as string, geometryFieldName: query.geometryFieldName as string, gridPrecision: parseInt(query.gridPrecision, 10), diff --git a/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js b/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js index 66eb54278e580..c8f1835a11647 100644 --- a/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js +++ b/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js @@ -44,6 +44,7 @@ export default function ({ getPageObjects, getService }) { delete searchParams.token; expect(searchParams).to.eql({ + buffer: 4, geometryFieldName: 'geo.coordinates', hasLabels: 'false', index: 'logstash-*', diff --git a/x-pack/test/functional/apps/maps/group4/mvt_scaling.js b/x-pack/test/functional/apps/maps/group4/mvt_scaling.js index 9bc23c8488ab9..80a7f8abc5d36 100644 --- a/x-pack/test/functional/apps/maps/group4/mvt_scaling.js +++ b/x-pack/test/functional/apps/maps/group4/mvt_scaling.js @@ -49,6 +49,7 @@ export default function ({ getPageObjects, getService }) { delete searchParams.token; expect(searchParams).to.eql({ + buffer: 4, geometryFieldName: 'geometry', hasLabels: 'false', index: 'geo_shapes*', From 1f03570126d2799b9b8e5294927269b1cb5087c9 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Thu, 9 Feb 2023 10:10:54 -0800 Subject: [PATCH 048/203] [Dashboard Usability] Moves scrollbar to panel section (#145628) ## Summary Closes https://github.com/elastic/kibana/issues/145404. Closes #134257. Cloud deployment for testing: https://kibana-pr-145628.kb.us-west2.gcp.elastic-cloud.com:9243 User: `elastic` Password: `zuIno5Tuy4lVmhMwbt2C6NyY` This moves the scrollbar from the entire app to only the panel section of the dashboard app. The search/filter bar and editor toolbar will remain at the top while controls and panels scroll. The controls floating actions were extracted out into their own component for future use for panel actions. #### Before ![Nov-17-2022 12-53-43](https://user-images.githubusercontent.com/1697105/202557972-6963b9d3-4eb0-40a4-963d-19e16e652d95.gif) #### After ![Nov-17-2022 12-41-29](https://user-images.githubusercontent.com/1697105/202557993-251a984e-8bce-4b50-94c7-a7a39410a624.gif) ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../component/control_frame_component.tsx | 42 ++++---- .../public/control_group/control_group.scss | 61 ++++------- .../public/dashboard_app/_dashboard_app.scss | 9 ++ .../public/dashboard_app/dashboard_app.tsx | 4 +- .../top_nav/dashboard_editing_toolbar.tsx | 13 ++- .../top_nav/dashboard_top_nav.tsx | 2 + .../_dashboard_container.scss | 4 +- .../component/grid/_dashboard_grid.scss | 2 - .../viewport/_dashboard_viewport.scss | 1 + .../component/viewport/dashboard_viewport.tsx | 62 ++++++++--- .../dashboard_container_renderer.tsx | 14 ++- .../embeddable/dashboard_container.tsx | 2 + .../panel/panel_header/panel_options_menu.tsx | 1 + .../floating_actions/floating_actions.tsx | 98 ++++++++++++++++++ .../public/components/index.tsx | 2 + .../solution_toolbar/solution_toolbar.scss | 1 - src/plugins/presentation_util/public/index.ts | 1 + .../options_list_creation_and_editing.ts | 55 +++++----- .../controls/range_slider.ts | 48 ++++----- .../functional/page_objects/dashboard_page.ts | 1 + .../baseline/dashboard_controls_dark.png | Bin 195119 -> 175127 bytes .../baseline/dashboard_controls_light.png | Bin 191495 -> 169693 bytes .../services/dashboard/add_panel.ts | 9 +- .../tooltip_popover.test.tsx.snap | 2 + .../tooltip_control/tooltip_popover.tsx | 1 + 25 files changed, 283 insertions(+), 152 deletions(-) create mode 100644 src/plugins/presentation_util/public/components/floating_actions/floating_actions.tsx diff --git a/src/plugins/controls/public/control_group/component/control_frame_component.tsx b/src/plugins/controls/public/control_group/component/control_frame_component.tsx index eb5cda421381d..d8aac356ce5ff 100644 --- a/src/plugins/controls/public/control_group/component/control_frame_component.tsx +++ b/src/plugins/controls/public/control_group/component/control_frame_component.tsx @@ -21,7 +21,7 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { Markdown } from '@kbn/kibana-react-plugin/public'; -import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public'; +import { useReduxEmbeddableContext, FloatingActions } from '@kbn/presentation-util-plugin/public'; import { ControlGroupReduxState } from '../types'; import { pluginServices } from '../../services'; import { EditControlButton } from '../editor/edit_control'; @@ -127,12 +127,7 @@ export const ControlFrame = ({ }, [embeddable, embeddableRoot]); const floatingActions = ( -
+ <> {!fatalError && embeddableType !== TIME_SLIDER_CONTROL && ( @@ -158,7 +153,7 @@ export const ControlFrame = ({ color="danger" /> -
+ ); const embeddableParentClassNames = classNames('controlFrame__control', { @@ -220,18 +215,27 @@ export const ControlFrame = ({ return ( <> - {embeddable && enableActions && floatingActions} - - {form} - + + {form} + + ); }; diff --git a/src/plugins/controls/public/control_group/control_group.scss b/src/plugins/controls/public/control_group/control_group.scss index a8db8cd943f5a..e2c88879c390f 100644 --- a/src/plugins/controls/public/control_group/control_group.scss +++ b/src/plugins/controls/public/control_group/control_group.scss @@ -181,48 +181,6 @@ $controlMinWidth: $euiSize * 14; } } - .controlFrameFloatingActions { - visibility: hidden; - opacity: 0; - - // slower transition on hover leave in case the user accidentally stops hover - transition: visibility .3s, opacity .3s; - - z-index: 1; - position: absolute; - - &--oneLine { - right: $euiSizeXS; - top: -$euiSizeL; - padding: $euiSizeXS; - border-radius: $euiBorderRadius; - background-color: $euiColorEmptyShade; - box-shadow: 0 0 0 1px $euiColorLightShade; - } - - &--fatalError { - right: $euiSizeXS; - top: -$euiSizeL; - padding: $euiSizeXS; - border-radius: $euiBorderRadius; - background-color: $euiColorEmptyShade; - box-shadow: 0 0 0 1px $euiColorLightShade; - } - - &--twoLine { - right: $euiSizeXS; - top: -$euiSizeXS; - } - } - - &:hover { - .controlFrameFloatingActions { - transition: visibility .1s, opacity .1s; - visibility: visible; - opacity: 1; - } - } - &-isDragging { .euiFormRow__labelWrapper { opacity: 0; @@ -232,3 +190,22 @@ $controlMinWidth: $euiSize * 14; } } } + +.controlFrameFloatingActions { + z-index: 1; + position: absolute; + + &--oneLine { + padding: $euiSizeXS; + border-radius: $euiBorderRadius; + background-color: $euiColorEmptyShade; + box-shadow: 0 0 0 1px $euiColorLightShade; + } + + &--fatalError { + padding: $euiSizeXS; + border-radius: $euiBorderRadius; + background-color: $euiColorEmptyShade; + box-shadow: 0 0 0 1px $euiColorLightShade; + } +} diff --git a/src/plugins/dashboard/public/dashboard_app/_dashboard_app.scss b/src/plugins/dashboard/public/dashboard_app/_dashboard_app.scss index 45a2d66e18b63..d212b0fcceed2 100644 --- a/src/plugins/dashboard/public/dashboard_app/_dashboard_app.scss +++ b/src/plugins/dashboard/public/dashboard_app/_dashboard_app.scss @@ -1,3 +1,12 @@ +@import 'src/core/public/mixins'; + +.dshAppWrapper { + @include kibanaFullBodyHeight(); + + display: flex; + flex-direction: column; +} + .dshUnsavedListingItem { margin-top: $euiSizeM; } diff --git a/src/plugins/dashboard/public/dashboard_app/dashboard_app.tsx b/src/plugins/dashboard/public/dashboard_app/dashboard_app.tsx index fd8334a246f32..774f4c1d92589 100644 --- a/src/plugins/dashboard/public/dashboard_app/dashboard_app.tsx +++ b/src/plugins/dashboard/public/dashboard_app/dashboard_app.tsx @@ -184,7 +184,7 @@ export function DashboardApp({ }, [dashboardContainer, kbnUrlStateStorage]); return ( - <> +
{showNoDataPage && ( setShowNoDataPage(false)} /> )} @@ -204,6 +204,6 @@ export function DashboardApp({ /> )} - +
); } diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx index 45d06f3cca87c..44041941bccc3 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_editing_toolbar.tsx @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { EuiHorizontalRule } from '@elastic/eui'; import { METRIC_TYPE } from '@kbn/analytics'; import { EmbeddableFactory } from '@kbn/embeddable-plugin/public'; import { @@ -19,6 +18,8 @@ import { import { BaseVisType, VisTypeAlias } from '@kbn/visualizations-plugin/public'; import React from 'react'; import { useCallback } from 'react'; +import { useEuiTheme } from '@elastic/eui'; +import { css } from '@emotion/react'; import { dashboardReplacePanelActionStrings } from '../../dashboard_actions/_dashboard_actions_strings'; import { DASHBOARD_APP_ID, DASHBOARD_UI_METRIC_ID } from '../../dashboard_constants'; import { useDashboardContainerContext } from '../../dashboard_container/dashboard_container_renderer'; @@ -36,6 +37,7 @@ export function DashboardEditingToolbar() { embeddable: { getStateTransfer, getEmbeddableFactory }, visualizations: { get: getVisualization, getAliases: getVisTypeAliases }, } = pluginServices.getServices(); + const { euiTheme } = useEuiTheme(); const { embeddableInstance: dashboardContainer } = useDashboardContainerContext(); @@ -178,8 +180,11 @@ export function DashboardEditingToolbar() { } return ( - <> - +
{{ primaryActionButton: ( @@ -195,6 +200,6 @@ export function DashboardEditingToolbar() { extraButtons, }} - +
); } diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx index 2181a66122ae4..41686c86a7078 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx @@ -18,6 +18,7 @@ import { ViewMode } from '@kbn/embeddable-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { TopNavMenuProps } from '@kbn/navigation-plugin/public'; +import { EuiHorizontalRule } from '@elastic/eui'; import { getDashboardTitle, leaveConfirmStrings, @@ -261,6 +262,7 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr ) : null} {viewMode === ViewMode.EDIT ? : null} + ); } diff --git a/src/plugins/dashboard/public/dashboard_container/_dashboard_container.scss b/src/plugins/dashboard/public/dashboard_container/_dashboard_container.scss index c4107d3f235ba..9019968040030 100644 --- a/src/plugins/dashboard/public/dashboard_container/_dashboard_container.scss +++ b/src/plugins/dashboard/public/dashboard_container/_dashboard_container.scss @@ -4,9 +4,9 @@ @import './component/panel/index'; @import './component/viewport/index'; -.dashboardViewport { - flex: 1; +.dashboardContainer, .dashboardViewport { display: flex; + flex: 1; flex-direction: column; } diff --git a/src/plugins/dashboard/public/dashboard_container/component/grid/_dashboard_grid.scss b/src/plugins/dashboard/public/dashboard_container/component/grid/_dashboard_grid.scss index bf593bd89b42b..450df53c0990a 100644 --- a/src/plugins/dashboard/public/dashboard_container/component/grid/_dashboard_grid.scss +++ b/src/plugins/dashboard/public/dashboard_container/component/grid/_dashboard_grid.scss @@ -33,8 +33,6 @@ */ .dshLayout-isMaximizedPanel { height: 100% !important; /* 1. */ - width: 100%; - position: absolute !important; /* 1 */ } /** diff --git a/src/plugins/dashboard/public/dashboard_container/component/viewport/_dashboard_viewport.scss b/src/plugins/dashboard/public/dashboard_container/component/viewport/_dashboard_viewport.scss index 5fc17b73bcd95..135a039e40357 100644 --- a/src/plugins/dashboard/public/dashboard_container/component/viewport/_dashboard_viewport.scss +++ b/src/plugins/dashboard/public/dashboard_container/component/viewport/_dashboard_viewport.scss @@ -8,6 +8,7 @@ .dshDashboardViewport-controls { margin: 0 $euiSizeS 0 $euiSizeS; + padding-top: $euiSizeS; padding-bottom: $euiSizeXS; } diff --git a/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx b/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx index 3e2b02f8ab761..09b17dc7afd27 100644 --- a/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx +++ b/src/plugins/dashboard/public/dashboard_container/component/viewport/dashboard_viewport.tsx @@ -11,24 +11,21 @@ import React, { useEffect, useRef } from 'react'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import { ExitFullScreenButton } from '@kbn/shared-ux-button-exit-full-screen'; +import { css } from '@emotion/react'; +import { EuiPortal } from '@elastic/eui'; import { DashboardGrid } from '../grid'; import { pluginServices } from '../../../services/plugin_services'; import { DashboardEmptyScreen } from '../empty_screen/dashboard_empty_screen'; import { useDashboardContainerContext } from '../../dashboard_container_renderer'; -export const DashboardViewport = () => { +export const DashboardViewportComponent = () => { const { settings: { isProjectEnabledInLabs }, } = pluginServices.getServices(); const controlsRoot = useRef(null); - const { - useEmbeddableDispatch, - useEmbeddableSelector: select, - actions: { setFullScreenMode }, - embeddableInstance: dashboardContainer, - } = useDashboardContainerContext(); - const dispatch = useEmbeddableDispatch(); + const { useEmbeddableSelector: select, embeddableInstance: dashboardContainer } = + useDashboardContainerContext(); /** * Render Control group @@ -47,9 +44,10 @@ export const DashboardViewport = () => { const dashboardTitle = select((state) => state.explicitInput.title); const useMargins = select((state) => state.explicitInput.useMargins); const description = select((state) => state.explicitInput.description); - const isFullScreenMode = select((state) => state.componentState.fullScreenMode); - const isEmbeddedExternally = select((state) => state.componentState.isEmbeddedExternally); - + const expandedPanelId = select((state) => state.componentState.expandedPanelId); + const expandedPanelStyles = css` + flex: 1; + `; const controlsEnabled = isProjectEnabledInLabs('labs:dashboard:dashboardControls'); return ( @@ -66,13 +64,8 @@ export const DashboardViewport = () => { data-title={dashboardTitle} data-description={description} className={useMargins ? 'dshDashboardViewport-withMargins' : 'dshDashboardViewport'} + css={expandedPanelId ? expandedPanelStyles : undefined} > - {isFullScreenMode && ( - dispatch(setFullScreenMode(false))} - toggleChrome={!isEmbeddedExternally} - /> - )} {panelCount === 0 && (
@@ -83,3 +76,38 @@ export const DashboardViewport = () => { ); }; + +// This fullscreen button HOC separates fullscreen button and dashboard content to reduce rerenders +// because ExitFullScreenButton sets isFullscreenMode to false on unmount while rerendering. +// This specifically fixed maximizing/minimizing panels without exiting fullscreen mode. +const WithFullScreenButton = ({ children }: { children: JSX.Element }) => { + const { + useEmbeddableDispatch, + useEmbeddableSelector: select, + actions: { setFullScreenMode }, + } = useDashboardContainerContext(); + const dispatch = useEmbeddableDispatch(); + + const isFullScreenMode = select((state) => state.componentState.fullScreenMode); + const isEmbeddedExternally = select((state) => state.componentState.isEmbeddedExternally); + + return ( + <> + {children} + {isFullScreenMode && ( + + dispatch(setFullScreenMode(false))} + toggleChrome={!isEmbeddedExternally} + /> + + )} + + ); +}; + +export const DashboardViewport = () => ( + + + +); diff --git a/src/plugins/dashboard/public/dashboard_container/dashboard_container_renderer.tsx b/src/plugins/dashboard/public/dashboard_container/dashboard_container_renderer.tsx index c6391abcbd611..09cb43051e1fe 100644 --- a/src/plugins/dashboard/public/dashboard_container/dashboard_container_renderer.tsx +++ b/src/plugins/dashboard/public/dashboard_container/dashboard_container_renderer.tsx @@ -10,10 +10,11 @@ import './_dashboard_container.scss'; import { v4 as uuidv4 } from 'uuid'; import classNames from 'classnames'; -import { EuiLoadingElastic, EuiLoadingSpinner } from '@elastic/eui'; import React, { useEffect, useMemo, useRef, useState } from 'react'; - import useObservable from 'react-use/lib/useObservable'; + +import { EuiLoadingElastic, EuiLoadingSpinner, useEuiOverflowScroll } from '@elastic/eui'; +import { css } from '@emotion/react'; import { useReduxEmbeddableContext } from '@kbn/presentation-util-plugin/public'; import { @@ -110,13 +111,20 @@ export const DashboardContainerRenderer = ({ { 'dashboardViewport--screenshotMode': isScreenshotMode() }, { 'dashboardViewport--loading': loading } ); + + const viewportStyles = css` + ${useEuiOverflowScroll('y', false)} + `; + const loadingSpinner = showPlainSpinner ? ( ) : ( ); return ( -
{loading ? loadingSpinner :
}
+
+ {loading ? loadingSpinner :
} +
); }; diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx index c2205d68ba546..3e3addaac6eee 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx @@ -417,6 +417,8 @@ export class DashboardContainer extends Container diff --git a/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx b/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx index 794b38b5a2514..61cdfeb90a9a4 100644 --- a/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx +++ b/src/plugins/embeddable/public/lib/panel/panel_header/panel_options_menu.tsx @@ -131,6 +131,7 @@ export class PanelOptionsMenu extends React.Component = ({ + className = '', + actions, + isEnabled, + usingTwoLineLayout, + children, +}) => { + const { euiTheme } = useEuiTheme(); + const anchorRef = useRef(null); + const actionsRef = useRef(null); + const [areFloatingActionsVisible, setFloatingActionsVisible] = useState(false); + + const showFloatingActions = useCallback( + () => isEnabled && setFloatingActionsVisible(true), + [isEnabled, setFloatingActionsVisible] + ); + const hideFloatingActions = useCallback( + () => setFloatingActionsVisible(false), + [setFloatingActionsVisible] + ); + + const anchorBoundingRect = anchorRef.current?.getBoundingClientRect(); + const actionsBoundingRect = actionsRef.current?.getBoundingClientRect(); + + const hiddenActionsStyles = ` + visibility: hidden; + opacity: 0; + + // slower transition on hover leave in case the user accidentally stops hover + transition: visibility 0.3s, opacity 0.3s; + `; + const visibleActionsStyles = ` + transition: visibility 0.1s, opacity 0.1s; + visibility: visible; + opacity: 1; + `; + + const floatingActionStyles = + anchorBoundingRect && actionsBoundingRect + ? css` + top: ${anchorBoundingRect.top - + (usingTwoLineLayout ? parseInt(euiTheme.size.xs, 10) : parseInt(euiTheme.size.l, 10))}px; + left: ${anchorBoundingRect.right - + actionsBoundingRect.width - + parseInt(euiTheme.size.xs, 10)}px; + + ${areFloatingActionsVisible ? visibleActionsStyles : hiddenActionsStyles} + ` + : undefined; + + return ( + <> + + {children} + + +
+ {actions} +
+
+ + ); +}; diff --git a/src/plugins/presentation_util/public/components/index.tsx b/src/plugins/presentation_util/public/components/index.tsx index fc5e97ad31736..fb66c9c5b2be6 100644 --- a/src/plugins/presentation_util/public/components/index.tsx +++ b/src/plugins/presentation_util/public/components/index.tsx @@ -42,6 +42,8 @@ export const LazyDataViewPicker = React.lazy(() => import('./data_view_picker/da export const LazyFieldPicker = React.lazy(() => import('./field_picker/field_picker')); +export { FloatingActions } from './floating_actions/floating_actions'; + /** * A lazily-loaded ExpressionInput component. */ diff --git a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.scss b/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.scss index 5b180c7097e4f..30ef3f1d2c44f 100644 --- a/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.scss +++ b/src/plugins/presentation_util/public/components/solution_toolbar/solution_toolbar.scss @@ -1,5 +1,4 @@ .solutionToolbar { - padding: $euiSize $euiSizeS; flex-grow: 0; // Temporary fix for two tone icons to make them monochrome diff --git a/src/plugins/presentation_util/public/index.ts b/src/plugins/presentation_util/public/index.ts index 504363208d6a0..24bcc6af474de 100644 --- a/src/plugins/presentation_util/public/index.ts +++ b/src/plugins/presentation_util/public/index.ts @@ -36,6 +36,7 @@ export { withSuspense, LazyDataViewPicker, LazyFieldPicker, + FloatingActions, } from './components'; export { diff --git a/test/functional/apps/dashboard_elements/controls/options_list/options_list_creation_and_editing.ts b/test/functional/apps/dashboard_elements/controls/options_list/options_list_creation_and_editing.ts index 2281c5ce112be..231994c2d1b8d 100644 --- a/test/functional/apps/dashboard_elements/controls/options_list/options_list_creation_and_editing.ts +++ b/test/functional/apps/dashboard_elements/controls/options_list/options_list_creation_and_editing.ts @@ -85,6 +85,17 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboard.clearUnsavedChanges(); }); + it('can make selections', async () => { + const firstId = (await dashboardControls.getAllControlIds())[0]; + await dashboardControls.optionsListOpenPopover(firstId); + await dashboardControls.optionsListPopoverSelectOption('win xp'); + await dashboardControls.optionsListPopoverSelectOption('osx'); + await dashboardControls.optionsListEnsurePopoverIsClosed(firstId); + + const selectionString = await dashboardControls.optionsListGetSelectionsString(firstId); + expect(selectionString).to.be('win xp, osx'); + }); + it('can add a second options list control with a non-default data view', async () => { await dashboardControls.createControl({ controlType: OPTIONS_LIST_CONTROL, @@ -98,18 +109,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboard.clearUnsavedChanges(); }); - it('renames an existing control', async () => { - const secondId = (await dashboardControls.getAllControlIds())[1]; - - const newTitle = 'wow! Animal sounds?'; - await dashboardControls.editExistingControl(secondId); - await dashboardControls.controlEditorSetTitle(newTitle); - await dashboardControls.controlEditorSave(); - expect(await dashboardControls.doesControlTitleExist(newTitle)).to.be(true); - await dashboard.clearUnsavedChanges(); - }); - - it('can change the data view and field of an existing options list', async () => { + it('can change the data view and field of an existing options list and clears selections', async () => { const firstId = (await dashboardControls.getAllControlIds())[0]; await dashboardControls.editExistingControl(firstId); @@ -120,6 +120,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboardControls.controlsEditorSetfield('animal.keyword', OPTIONS_LIST_CONTROL); await dashboardControls.controlEditorSave(); + const selectionString = await dashboardControls.optionsListGetSelectionsString(firstId); + expect(selectionString).to.be('Any'); + // when creating a new filter, the ability to select a data view should be removed, because the dashboard now only has one data view await retry.try(async () => { await testSubjects.click('addFilter'); @@ -127,37 +130,27 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await filterBar.ensureFieldEditorModalIsClosed(); expect(indexPatternSelectExists).to.be(false); }); - await dashboard.clearUnsavedChanges(); }); - it('editing field clears selections', async () => { + it('renames an existing control and retains selection', async () => { const secondId = (await dashboardControls.getAllControlIds())[1]; + await dashboardControls.optionsListOpenPopover(secondId); await dashboardControls.optionsListPopoverSelectOption('hiss'); await dashboardControls.optionsListEnsurePopoverIsClosed(secondId); + const newTitle = 'wow! Animal sounds?'; + await testSubjects.click(`control-action-${secondId}-edit`); await dashboardControls.editExistingControl(secondId); - await dashboardControls.controlsEditorSetfield('animal.keyword', OPTIONS_LIST_CONTROL); + await dashboardControls.controlEditorSetTitle(newTitle); + await dashboardControls.controlEditorSetWidth('small'); await dashboardControls.controlEditorSave(); + expect(await dashboardControls.doesControlTitleExist(newTitle)).to.be(true); const selectionString = await dashboardControls.optionsListGetSelectionsString(secondId); - expect(selectionString).to.be('Any'); - }); - - it('editing other control settings keeps selections', async () => { - const secondId = (await dashboardControls.getAllControlIds())[1]; - await dashboardControls.optionsListOpenPopover(secondId); - await dashboardControls.optionsListPopoverSelectOption('dog'); - await dashboardControls.optionsListPopoverSelectOption('cat'); - await dashboardControls.optionsListEnsurePopoverIsClosed(secondId); - - await dashboardControls.editExistingControl(secondId); - await dashboardControls.controlEditorSetTitle('Animal'); - await dashboardControls.controlEditorSetWidth('large'); - await dashboardControls.controlEditorSave(); + expect(selectionString).to.be('hiss'); - const selectionString = await dashboardControls.optionsListGetSelectionsString(secondId); - expect(selectionString).to.be('dog, cat'); + await dashboard.clearUnsavedChanges(); }); it('deletes an existing control', async () => { diff --git a/test/functional/apps/dashboard_elements/controls/range_slider.ts b/test/functional/apps/dashboard_elements/controls/range_slider.ts index 17d787b55c5d1..fa075093fcbec 100644 --- a/test/functional/apps/dashboard_elements/controls/range_slider.ts +++ b/test/functional/apps/dashboard_elements/controls/range_slider.ts @@ -80,6 +80,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboard.clearUnsavedChanges(); }); + it('can select a range', async () => { + const firstId = (await dashboardControls.getAllControlIds())[0]; + await dashboardControls.rangeSliderSetLowerBound(firstId, '50'); + await dashboardControls.rangeSliderSetUpperBound(firstId, '100'); + await dashboardControls.validateRange('value', firstId, '50', '100'); + + await dashboard.clearUnsavedChanges(); + }); + it('can add a second range list control with a non-default data view', async () => { await dashboardControls.createControl({ controlType: RANGE_SLIDER_CONTROL, @@ -90,22 +99,29 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await dashboardControls.getControlsCount()).to.be(2); const secondId = (await dashboardControls.getAllControlIds())[1]; await dashboardControls.validateRange('placeholder', secondId, '100', '1200'); + + await dashboardControls.rangeSliderSetLowerBound(secondId, '200'); + await dashboardControls.rangeSliderSetUpperBound(secondId, '1000'); + await dashboardControls.validateRange('value', secondId, '200', '1000'); + // data views should be properly propagated from the control group to the dashboard expect(await filterBar.getIndexPatterns()).to.be('logstash-*,kibana_sample_data_flights'); await dashboard.clearUnsavedChanges(); }); - it('renames an existing control', async () => { + it('edits title and size of an existing control and retains existing range selection', async () => { const secondId = (await dashboardControls.getAllControlIds())[1]; const newTitle = 'Average ticket price'; await dashboardControls.editExistingControl(secondId); await dashboardControls.controlEditorSetTitle(newTitle); + await dashboardControls.controlEditorSetWidth('large'); await dashboardControls.controlEditorSave(); expect(await dashboardControls.doesControlTitleExist(newTitle)).to.be(true); + await dashboardControls.validateRange('value', secondId, '200', '1000'); await dashboard.clearUnsavedChanges(); }); - it('can edit range slider control', async () => { + it('can change data view and field of range slider control and clears existing selection', async () => { const firstId = (await dashboardControls.getAllControlIds())[0]; await dashboardControls.editExistingControl(firstId); @@ -117,6 +133,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboardControls.controlEditorSave(); await dashboardControls.rangeSliderWaitForLoading(); await dashboardControls.validateRange('placeholder', firstId, '0', '6'); + await dashboardControls.validateRange('value', firstId, '', ''); // when creating a new filter, the ability to select a data view should be removed, because the dashboard now only has one data view await retry.try(async () => { @@ -152,37 +169,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboardControls.rangeSliderWaitForLoading(); const secondId = (await dashboardControls.getAllControlIds())[1]; await dashboardControls.validateRange('placeholder', secondId, '100', '1000'); - }); - - it('editing field clears selections', async () => { - const secondId = (await dashboardControls.getAllControlIds())[1]; - await dashboardControls.editExistingControl(secondId); - await dashboardControls.controlsEditorSetfield('FlightDelayMin', RANGE_SLIDER_CONTROL); - await dashboardControls.controlEditorSave(); - - await dashboardControls.rangeSliderWaitForLoading(); - await dashboardControls.validateRange('value', secondId, '', ''); - }); - - it('editing other control settings keeps selections', async () => { - const secondId = (await dashboardControls.getAllControlIds())[1]; - await dashboardControls.rangeSliderSetLowerBound(secondId, '50'); - await dashboardControls.rangeSliderSetUpperBound(secondId, '100'); - await dashboardControls.rangeSliderWaitForLoading(); - - await dashboardControls.editExistingControl(secondId); - await dashboardControls.controlEditorSetTitle('Minimum Flight Delay'); - await dashboardControls.controlEditorSetWidth('large'); - await dashboardControls.controlEditorSave(); - - await dashboardControls.rangeSliderWaitForLoading(); - await dashboardControls.validateRange('value', secondId, '50', '100'); + await dashboard.clearUnsavedChanges(); }); it('can clear out selections by clicking the reset button', async () => { const firstId = (await dashboardControls.getAllControlIds())[0]; await dashboardControls.rangeSliderClearSelection(firstId); await dashboardControls.validateRange('value', firstId, '', ''); + await dashboardControls.rangeSliderEnsurePopoverIsClosed(firstId); await dashboard.clearUnsavedChanges(); }); diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index 1f9656c9ff548..1bfcf354b1086 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -325,6 +325,7 @@ export class DashboardPageObject extends FtrService { await this.testSubjects.existOrFail('dashboardUnsavedChangesBadge'); await this.clickQuickSave(); await this.testSubjects.missingOrFail('dashboardUnsavedChangesBadge'); + await this.testSubjects.click('toastCloseButton'); }); if (switchMode) { await this.clickCancelOutOfEditMode(); diff --git a/test/functional/screenshots/baseline/dashboard_controls_dark.png b/test/functional/screenshots/baseline/dashboard_controls_dark.png index 542f90499166d82fb20b4960ffdfcb6b6ba71f57..bbaf629710c14df27f23816a95aaf75840ac240a 100644 GIT binary patch literal 175127 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

|6~ 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

FmqbyunIJsZe-%RCnv0!d+kQ{H({b| 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 literal 191495 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

)SWf^wE{}jPcbSI$0~+ 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 { pointerEvents: 'none', transform: `translate(${this.state.x - 13 - offset}px, ${this.state.y - 13}px)`, }} + repositionOnScroll > {this._renderTooltipContent()} From 26eddec70844ffb65e5d3521a7adb52e643c4534 Mon Sep 17 00:00:00 2001 From: Marco Antonio Ghiani Date: Thu, 9 Feb 2023 19:19:10 +0100 Subject: [PATCH 049/203] [Infrastructure UI] Track host cloud provider on table entry click (#150685) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📓 Summary Closes #150681 The tracked event when clicking an entry from the Hosts table was not applying correctly the default `unknow` string for the `cloud_provider` parameter. Now it defaults to it in case the value is not passed or is null. ## 🧪 Testing - Navigate to the Hosts view - Open the console dev tools - Click on a host name from the table and navigate to the host detail. - Verify the following error does not appear in the log ``` Uncaught Error: Failed to validate payload coming from "Event Type 'Host Entry Clicked'": [cloud_provider]: {"expected":"string","actual":"object","value":null} ``` Co-authored-by: Marco Antonio Ghiani --- .../infra/public/services/telemetry/telemetry_client.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts b/x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts index 642611001b287..66ee3220c2935 100644 --- a/x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts +++ b/x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts @@ -22,11 +22,11 @@ export class TelemetryClient implements ITelemetryClient { public reportHostEntryClicked = ({ hostname, - cloud_provider: cloudProvider = 'unknown', + cloud_provider: cloudProvider, }: HostEntryClickedParams) => { this.analytics.reportEvent(InfraTelemetryEventTypes.HOSTS_ENTRY_CLICKED, { hostname, - cloud_provider: cloudProvider, + cloud_provider: cloudProvider ?? 'unknown', }); }; From 5d4c88057355062f92f01f570a0efc42e25b3483 Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Thu, 9 Feb 2023 11:32:32 -0700 Subject: [PATCH 050/203] [Dashboard] [Navigation] Fix mount point bug (#150507) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes https://github.com/elastic/kibana/issues/150371 ## Summary Oooh, man. This was a fun one! Okay, so. To try to understand this bug, we first have to understand a little bit about how the header action menu is rendered as part of the `TopNavMenu` component (in `dashboard_top_nav.tsx`). Essentially, as part of rendering `TopNavMenu`, a `MountPointPortal` is created for the `headerActionMenu` so that the items get rendered in the correct location, like so: ![WithAndWithoutPortal](https://user-images.githubusercontent.com/8698078/217674254-cd27470b-fcce-4cb9-b960-51ea2b8a68c8.png) When there is **no** filter pill (i.e. `showSearchBar` is `false`), this `MountPointPortal` gets **unmounted** alongside the search bar as part of the `TopNavMenu` component (after all, only the dashboard viewport is getting rendered in this scenario). When you exit fullscreen mode, both the search bar and the `MountPointPortal` get re-mounted, which triggers a re-render, and so the `headerActionMenu` shows up as expected. Now, consider what happens when there **is** a filter pill (i.e. when `showSearchBar` is `true`). Because the search bar still needs to get rendered, neither it **nor** the `MountPointPortal` get unmounted - instead, the search bar simply gets re-rendered while the portal gets updated to point at an element that no longer exists (since the place where the `headerActionMenu` normally gets rendered is no longer present). Now, when you exit fullscreen mode, neither element needs to get re-mounted - they simply need to get re-rendered. Everything works great for the search bar, but the `headerActionMenu` seems to be rendering itself **before** the portal gets a chance to point to the correct place again - so, it doesn't show up unless a re-render of `TopNavMenu` is manually triggered (like, say, by removing the filter pill): https://user-images.githubusercontent.com/8698078/217868558-7eb73df8-3417-4d5a-ab5d-e7c9138532a9.mov So essentially, from what I can understand, this bug comes down to a race condition between the `MountPointPortal` telling the `headerActionMenu` **where** to render and the `TopNavMenu` actually rendering. Since the `MountPointPortal` **is not necessary** in fullscreen mode, regardless of if `showSearchBar` is `true` or `false`, the best way to prevent this bug is to simply ensure that it **always** gets unmounted when entering fullscreen mode - this ensures that the rendering always happens in the order that it is meant to. This can be accomplished by setting the `MenuMountPoint` to `undefined` when the dashboard enters fullscreen mode. As far as why this bug only happened on **click** and not when the escape key was hit... For some reason (React magic 🤷), hitting the escape key causes two renders of the `TopNavMenu` component whereas clicking the button only causes a single render. This means that, by the time the second render occurs when hitting escape, `MountPointPortal` has had a chance to update - hence, why the menu shows up where it's supposed to. ### Checklist - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../top_nav/dashboard_top_nav.tsx | 80 ++++++++++--------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx index 41686c86a7078..6a5e7a8b0162e 100644 --- a/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/dashboard_app/top_nav/dashboard_top_nav.tsx @@ -16,7 +16,6 @@ import { } from '@kbn/presentation-util-plugin/public'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; -import type { TopNavMenuProps } from '@kbn/navigation-plugin/public'; import { EuiHorizontalRule } from '@elastic/eui'; import { @@ -68,7 +67,6 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr } = pluginServices.getServices(); const isLabsEnabled = uiSettings.get(UI_SETTINGS.ENABLE_LABS_UI); const { setHeaderActionMenu, onAppLeave } = useDashboardMountContext(); - /** * Unpack dashboard state from redux */ @@ -187,10 +185,9 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr setIsLabsShown, }); - const getNavBarProps = (): TopNavMenuProps => { + const visibilityProps = useMemo(() => { const shouldShowNavBarComponent = (forceShow: boolean): boolean => (forceShow || isChromeVisible) && !fullScreenMode; - const shouldShowFilterBar = (forceHide: boolean): boolean => !forceHide && (filterManager.getFilters().length > 0 || !fullScreenMode); @@ -202,46 +199,15 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr const showFilterBar = shouldShowFilterBar(Boolean(embedSettings?.forceHideFilterBar)); const showQueryBar = showQueryInput || showDatePicker || showFilterBar; const showSearchBar = showQueryBar || showFilterBar; - const topNavConfig = viewMode === ViewMode.EDIT ? editModeTopNavConfig : viewModeTopNavConfig; - - const badges = - hasUnsavedChanges && viewMode === ViewMode.EDIT - ? [ - { - 'data-test-subj': 'dashboardUnsavedChangesBadge', - badgeText: unsavedChangesBadgeStrings.getUnsavedChangedBadgeText(), - color: 'success', - }, - ] - : undefined; return { - query, - badges, - savedQueryId, + showTopNavMenu, showSearchBar, showFilterBar, - showSaveQuery, showQueryInput, showDatePicker, - screenTitle: title, - useDefaultBehaviors: true, - appName: LEGACY_DASHBOARD_APP_ID, - visible: viewMode !== ViewMode.PRINT, - indexPatterns: allDataViews, - config: showTopNavMenu ? topNavConfig : undefined, - setMenuMountPoint: embedSettings ? undefined : setHeaderActionMenu, - className: fullScreenMode ? 'kbnTopNavMenu-isFullScreen' : undefined, - onQuerySubmit: (_payload, isUpdate) => { - if (isUpdate === false) { - dashboardContainer.forceRefresh(); - } - }, - onSavedQueryIdChange: (newId: string | undefined) => { - dispatch(setSavedQueryId(newId)); - }, }; - }; + }, [embedSettings, filterManager, fullScreenMode, isChromeVisible, viewMode]); UseUnmount(() => { dashboardContainer.clearOverlays(); @@ -255,7 +221,45 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr ref={dashboardTitleRef} tabIndex={-1} >{`${getDashboardBreadcrumb()} - ${dashboardTitle}`}

- + { + if (isUpdate === false) { + dashboardContainer.forceRefresh(); + } + }} + onSavedQueryIdChange={(newId: string | undefined) => { + dispatch(setSavedQueryId(newId)); + }} + /> {viewMode !== ViewMode.PRINT && isLabsEnabled && isLabsShown ? ( setIsLabsShown(false)} /> From 13f5c4c5583a4e2db7149f1315744f6d54eb6102 Mon Sep 17 00:00:00 2001 From: Jeramy Soucy Date: Thu, 9 Feb 2023 14:19:43 -0500 Subject: [PATCH 051/203] Fixes the space selector page layout (#150503) closes #150319 Use of the KibanaPageTemplate.EmptyPrompt on the space selector page was causing the grid of space cards to render in only 2 columns. After trying to tweak several properties (e.g. restrictWidth, etc.), only removing the EmptyPrompt or changing it to a KibanaPageTemplate.Section solved the issue. EmptyPrompt Render: Screenshot 2023-02-07 at 5 13 03 PM New Section Render: Screenshot 2023-02-08 at 5 06 45 PM --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../space_selector.test.tsx.snap | 25 +++++++++--------- .../public/space_selector/space_selector.tsx | 26 +++++++++---------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap b/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap index 7e274515d8276..8a24945424379 100644 --- a/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap +++ b/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap @@ -6,8 +6,9 @@ exports[`it renders without crashing 1`] = ` data-test-subj="kibanaSpaceSelector" panelled={true} > - <_EuiPageEmptyPrompt + <_EuiPageSection className="spcSpaceSelector__pageContent" + color="transparent" > -

- -

+

+ +

- + `; diff --git a/x-pack/plugins/spaces/public/space_selector/space_selector.tsx b/x-pack/plugins/spaces/public/space_selector/space_selector.tsx index 2596c6867b8e0..a19745ba2c34e 100644 --- a/x-pack/plugins/spaces/public/space_selector/space_selector.tsx +++ b/x-pack/plugins/spaces/public/space_selector/space_selector.tsx @@ -107,23 +107,23 @@ export class SpaceSelector extends Component { data-test-subj="kibanaSpaceSelector" panelled > - + -

- -

+

+ +

{ )} - + ); } From d14759340b3debd80d0492e6e3d3988cc71933ad Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Thu, 9 Feb 2023 13:22:26 -0600 Subject: [PATCH 052/203] [Security Solution] fix flaky endpoint tests (#150652) Fixes https://github.com/elastic/kibana/issues/72874 --- x-pack/plugins/security_solution/server/plugin.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 6dee0730b5aa3..db7a32670727b 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -529,11 +529,13 @@ export class Plugin implements ISecuritySolutionPlugin { this.telemetryReceiver ); - if (plugins.taskManager) { - this.checkMetadataTransformsTask?.start({ - taskManager: plugins.taskManager, - }); - } + plugins.fleet?.fleetSetupCompleted().then(() => { + if (plugins.taskManager) { + this.checkMetadataTransformsTask?.start({ + taskManager: plugins.taskManager, + }); + } + }); return {}; } From fa44054f06e2217ee6a5fbed499a77da60df12db Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Thu, 9 Feb 2023 20:40:08 +0100 Subject: [PATCH 053/203] [Enterprise Search] Move pipelines modal to flyout (#150727) ## Summary This moves the pipeline settings modal to a flyout. Screenshot 2023-02-09 at 16 21 20 --- .../customize_pipeline_item.tsx | 2 +- .../default_pipeline_item.test.tsx | 4 +- .../default_pipeline_item.tsx | 6 +- ...e_modal.tsx => ingest_pipeline_flyout.tsx} | 108 +++++++++--------- .../ingest_pipelines_card.tsx | 15 +-- .../pipelines/pipelines_logic.test.ts | 28 ++--- .../search_index/pipelines/pipelines_logic.ts | 22 ++-- .../translations/translations/fr-FR.json | 22 ++-- .../translations/translations/ja-JP.json | 22 ++-- .../translations/translations/zh-CN.json | 22 ++-- 10 files changed, 129 insertions(+), 122 deletions(-) rename x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/{ingest_pipeline_modal.tsx => ingest_pipeline_flyout.tsx} (75%) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/customize_pipeline_item.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/customize_pipeline_item.tsx index a16274b26236d..96d213ced0f2d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/customize_pipeline_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/customize_pipeline_item.tsx @@ -56,7 +56,7 @@ export const CustomizeIngestPipelineItem: React.FC = () => { onClick={() => createCustomPipeline({ indexName })} > {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.copyButtonLabel', + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.copyButtonLabel', { defaultMessage: 'Copy and customize' } )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.test.tsx index 29bcd0b03dbd3..abc5c36de1144 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.test.tsx @@ -28,7 +28,7 @@ describe('DefaultPipelineItem', () => { index={index} indexName={index.name} ingestionMethod={ingestionMethod} - openModal={mockOpenModal} + openPipelineSettings={mockOpenModal} pipelineName={mockPipelineState.name} pipelineState={mockPipelineState} /> @@ -58,7 +58,7 @@ describe('DefaultPipelineItem', () => { index={index} indexName={index.name} ingestionMethod={ingestionMethod} - openModal={mockOpenModal} + openPipelineSettings={mockOpenModal} pipelineName={mockPipelineState.name} pipelineState={mockPipelineState} /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.tsx index 576c3e304a443..ddc5d6f4d65df 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/default_pipeline_item.tsx @@ -28,10 +28,10 @@ export const DefaultPipelineItem: React.FC<{ index: ElasticsearchIndexWithIngestion; indexName: string; ingestionMethod: string; - openModal: () => void; + openPipelineSettings: () => void; pipelineName: string; pipelineState: IngestPipelineParams; -}> = ({ index, indexName, ingestionMethod, openModal, pipelineName, pipelineState }) => { +}> = ({ index, indexName, ingestionMethod, openPipelineSettings, pipelineName, pipelineState }) => { /** * If we don't open the accordion on load, the curl code never shows the copy button * Because if the accordion is closed, the code block is not present in the DOM @@ -57,7 +57,7 @@ export const DefaultPipelineItem: React.FC<{ {i18n.translate( 'xpack.enterpriseSearch.content.indices.pipelines.ingestPipelinesCard.settings.label', diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_modal.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_flyout.tsx similarity index 75% rename from x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_modal.tsx rename to x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_flyout.tsx index d7bfe52a803e1..f570660ae73e7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_modal.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipeline_flyout.tsx @@ -15,13 +15,13 @@ import { EuiForm, EuiFormRow, EuiLink, - EuiModal, - EuiModalBody, - EuiModalFooter, - EuiModalHeader, - EuiModalHeaderTitle, + EuiFlyout, + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyoutHeader, EuiSpacer, EuiText, + EuiTitle, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -34,8 +34,8 @@ import { CurlRequest } from '../../components/curl_request/curl_request'; import { PipelineSettingsForm } from '../pipeline_settings_form'; -interface IngestPipelineModalProps { - closeModal: () => void; +interface IngestPipelineFlyoutProps { + closeFlyout: () => void; displayOnly: boolean; indexName: string; ingestionMethod: string; @@ -45,8 +45,8 @@ interface IngestPipelineModalProps { setPipeline: (pipeline: IngestPipelineParams) => void; } -export const IngestPipelineModal: React.FC = ({ - closeModal, +export const IngestPipelineFlyout: React.FC = ({ + closeFlyout, displayOnly, indexName, ingestionMethod, @@ -58,18 +58,20 @@ export const IngestPipelineModal: React.FC = ({ const { name } = pipeline; return ( - - + + - - {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalHeaderTitle', - { - defaultMessage: 'Pipeline settings', - } - )} - + +

+ {i18n.translate( + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalHeaderTitle', + { + defaultMessage: 'Pipeline settings', + } + )} +

+ @@ -77,8 +79,8 @@ export const IngestPipelineModal: React.FC = ({ - - + + @@ -88,13 +90,13 @@ export const IngestPipelineModal: React.FC = ({ <>

{i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.apiIndex', + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.apiIndex', { defaultMessage: 'This is an API-based index.' } )} @@ -104,7 +106,7 @@ export const IngestPipelineModal: React.FC = ({

{i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyAPITextCont', + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyAPITextCont', { defaultMessage: "In order to use this pipeline on your API-based indices you'll need to explicitly reference it in your API requests.", @@ -114,7 +116,7 @@ export const IngestPipelineModal: React.FC = ({ ) : ( i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyConnectorText', + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyConnectorText', { defaultMessage: 'This pipeline runs automatically on all Crawler and Connector indices created through Enterprise Search.', @@ -127,7 +129,7 @@ export const IngestPipelineModal: React.FC = ({ {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalIngestLinkLabel', + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalIngestLinkLabel', { defaultMessage: 'Learn more about Enterprise Search ingest pipelines', } @@ -168,7 +170,7 @@ export const IngestPipelineModal: React.FC = ({ {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.curlHeader', + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.curlHeader', { defaultMessage: 'Sample cURL request to ingest a document', } @@ -185,38 +187,42 @@ export const IngestPipelineModal: React.FC = ({ )} - - + + {displayOnly ? ( - + {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.closeButtonLabel', + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.closeButtonLabel', { defaultMessage: 'Close', } )} ) : ( - <> - - {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.cancelButtonLabel', - { - defaultMessage: 'Cancel', - } - )} - - - {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestModal.saveButtonLabel', - { - defaultMessage: 'Save', - } - )} - - + + + + {i18n.translate( + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.cancelButtonLabel', + { + defaultMessage: 'Cancel', + } + )} + + + + + {i18n.translate( + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.saveButtonLabel', + { + defaultMessage: 'Save', + } + )} + + + )} - - + + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.tsx index 92ec7ac7c0105..d57b4142d2905 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.tsx @@ -19,7 +19,7 @@ import { PipelinesLogic } from '../pipelines_logic'; import { CustomPipelineItem } from './custom_pipeline_item'; import { CustomizeIngestPipelineItem } from './customize_pipeline_item'; import { DefaultPipelineItem } from './default_pipeline_item'; -import { IngestPipelineModal } from './ingest_pipeline_modal'; +import { IngestPipelineFlyout } from './ingest_pipeline_flyout'; export const IngestPipelinesCard: React.FC = () => { const { indexName, ingestionMethod } = useValues(IndexViewLogic); @@ -30,9 +30,10 @@ export const IngestPipelinesCard: React.FC = () => { index, pipelineName, pipelineState, - showModal, + showPipelineSettings, } = useValues(PipelinesLogic); - const { closeModal, openModal, setPipelineState, savePipeline } = useActions(PipelinesLogic); + const { closePipelineSettings, openPipelineSettings, setPipelineState, savePipeline } = + useActions(PipelinesLogic); const { makeRequest: fetchCustomPipeline } = useActions(FetchCustomPipelineApiLogic); const { data: customPipelines } = useValues(FetchCustomPipelineApiLogic); @@ -46,9 +47,9 @@ export const IngestPipelinesCard: React.FC = () => { <> {!hasIndexIngestionPipeline && } - {showModal && ( - { { @@ -72,11 +72,11 @@ describe('PipelinesLogic', () => { }); describe('actions', () => { - it('should set showModal to false and call fetchApiSuccess', async () => { + it('should set showPipelineSettings to false and call fetchApiSuccess', async () => { CachedFetchIndexApiLogic.actions.apiSuccess(connectorIndex); PipelinesLogic.actions.fetchIndexApiSuccess = jest.fn(); PipelinesLogic.actions.setPipelineState(newPipeline); - PipelinesLogic.actions.openModal(); + PipelinesLogic.actions.openPipelineSettings(); PipelinesLogic.actions.apiSuccess({ connectorId: 'a', pipeline: newPipeline }); expect(PipelinesLogic.values).toEqual({ ...DEFAULT_VALUES, @@ -113,17 +113,17 @@ describe('PipelinesLogic', () => { expect(clearFlashMessages).toHaveBeenCalled(); }); }); - describe('openModal', () => { - it('should set showModal to true', () => { - PipelinesLogic.actions.openModal(); - expect(PipelinesLogic.values).toEqual({ ...DEFAULT_VALUES, showModal: true }); + describe('openPipelineSettings', () => { + it('should set showPipelineSettings to true', () => { + PipelinesLogic.actions.openPipelineSettings(); + expect(PipelinesLogic.values).toEqual({ ...DEFAULT_VALUES, showPipelineSettings: true }); }); }); - describe('closeModal', () => { - it('should set showModal to false', () => { - PipelinesLogic.actions.openModal(); - PipelinesLogic.actions.closeModal(); - expect(PipelinesLogic.values).toEqual({ ...DEFAULT_VALUES, showModal: false }); + describe('closePipelineSettings', () => { + it('should set showPipelineSettings to false', () => { + PipelinesLogic.actions.openPipelineSettings(); + PipelinesLogic.actions.closePipelineSettings(); + expect(PipelinesLogic.values).toEqual({ ...DEFAULT_VALUES, showPipelineSettings: false }); }); }); describe('apiError', () => { @@ -180,7 +180,7 @@ describe('PipelinesLogic', () => { }); }); it('should not set configState if modal is open', () => { - PipelinesLogic.actions.openModal(); + PipelinesLogic.actions.openPipelineSettings(); PipelinesLogic.actions.fetchIndexApiSuccess({ ...connectorIndex, connector: { ...connectorIndex.connector, pipeline: newPipeline }, @@ -192,7 +192,7 @@ describe('PipelinesLogic', () => { connector: { ...connectorIndex.connector, pipeline: newPipeline }, }, indexName: 'connector', - showModal: true, + showPipelineSettings: true, }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts index 134155f88a64c..dbe0239028ad5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.ts @@ -77,7 +77,7 @@ type PipelinesActions = Pick< AttachMlInferencePipelineResponse >['apiSuccess']; closeAddMlInferencePipelineModal: () => void; - closeModal: () => void; + closePipelineSettings: () => void; createCustomPipeline: Actions< CreateCustomPipelineApiLogicArgs, CreateCustomPipelineApiLogicResponse @@ -132,7 +132,7 @@ type PipelinesActions = Pick< fetchMlInferenceProcessors: typeof FetchMlInferencePipelineProcessorsApiLogic.actions.makeRequest; fetchMlInferenceProcessorsApiError: (error: HttpError) => HttpError; openAddMlInferencePipelineModal: () => void; - openModal: () => void; + openPipelineSettings: () => void; savePipeline: () => void; setPipelineState(pipeline: IngestPipelineParams): { pipeline: IngestPipelineParams; @@ -152,15 +152,15 @@ interface PipelinesValues { pipelineName: string; pipelineState: IngestPipelineParams; showAddMlInferencePipelineModal: boolean; - showModal: boolean; + showPipelineSettings: boolean; } export const PipelinesLogic = kea>({ actions: { closeAddMlInferencePipelineModal: true, - closeModal: true, + closePipelineSettings: true, openAddMlInferencePipelineModal: true, - openModal: true, + openPipelineSettings: true, savePipeline: true, setPipelineState: (pipeline: IngestPipelineParams) => ({ pipeline }), }, @@ -241,7 +241,7 @@ export const PipelinesLogic = kea + closePipelineSettings: () => actions.setPipelineState( isConnectorIndex(values.index) || isCrawlerIndex(values.index) ? values.index.connector?.pipeline ?? values.defaultPipelineValues @@ -297,7 +297,7 @@ export const PipelinesLogic = kea { - if (!values.showModal) { + if (!values.showPipelineSettings) { // Don't do this when the modal is open to avoid overwriting the values while editing const pipeline = isConnectorIndex(index) || isCrawlerIndex(index) @@ -306,7 +306,7 @@ export const PipelinesLogic = kea { + openPipelineSettings: () => { const pipeline = isCrawlerIndex(values.index) || isConnectorIndex(values.index) ? values.index.connector?.pipeline @@ -341,12 +341,12 @@ export const PipelinesLogic = kea true, }, ], - showModal: [ + showPipelineSettings: [ false, { apiSuccess: () => false, - closeModal: () => false, - openModal: () => true, + closePipelineSettings: () => false, + openPipelineSettings: () => true, }, ], }), diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index d46c9c86ef94e..2608edfdd2dfe 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -10559,7 +10559,7 @@ "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.crawler.subheading": "Vos logs du robot d'indexation sont actuellement stockés pendant {minAgeDays} jours.", "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.prompt": "Tapez \"{target}\" pour confirmer.", "xpack.enterpriseSearch.appSearch.sourceEngines.removeEngineConfirmDialogue.description": "Le moteur \"{engineName}\" sera retiré de ce métamoteur. Tous les paramètres existants seront perdus. Voulez-vous vraiment continuer ?", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyAPIText": "{apiIndex} Les modifications apportées aux paramètres ci-dessous sont uniquement fournies à titre indicatif. Ces paramètres ne seront pas conservés dans votre index ou pipeline.", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyAPIText": "{apiIndex} Les modifications apportées aux paramètres ci-dessous sont uniquement fournies à titre indicatif. Ces paramètres ne seront pas conservés dans votre index ou pipeline.", "xpack.enterpriseSearch.content.indices.callout.text": "Vos index Elasticsearch sont maintenant au premier plan d'Enterprise Search. Vous pouvez créer des index et lancer directement des expériences de recherche avec ces index. Pour en savoir plus sur l'utilisation des index de recherche Elasticsearch dans Enterprise Search {docLink}", "xpack.enterpriseSearch.content.indices.configurationConnector.apiKey.description": "D'abord, générez une clé d'API Elasticsearch. Cette clé {apiKeyName} permet d'activer les autorisations de lecture et d'écriture du connecteur pour qu'il puisse indexer les documents dans l'index {indexName} créé. Enregistrez cette clé en lieu sûr, car vous en aurez besoin pour configurer votre connecteur.", "xpack.enterpriseSearch.content.indices.configurationConnector.config.description.firstParagraph": "Maintenant que votre connecteur est déployé, améliorez le client du connecteur déployé pour votre source de données personnalisée. Voici le lien ({link}) qui vous permet de commencer à ajouter la logique d'implémentation spécifique à votre source de données.", @@ -11608,16 +11608,16 @@ "xpack.enterpriseSearch.content.index.filtering.value": "Valeur", "xpack.enterpriseSearch.content.index.pipelines.copyAndCustomize.description": "Vous pouvez créer une version de cette configuration spécifique à l'index et la modifier pour votre cas d'utilisation.", "xpack.enterpriseSearch.content.index.pipelines.copyAndCustomize.platinumText": "Avec une licence Platinum, vous pouvez créer une version de cette configuration spécifique à l'index et la modifier pour votre cas d'utilisation.", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.apiIndex": "Il s'agit d'un index basé sur l'API.", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.cancelButtonLabel": "Annuler", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.closeButtonLabel": "Fermer", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.copyButtonLabel": "Copier et personnaliser", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.curlHeader": "Exemple de requête cURL pour ingérer un document", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyAPITextCont": "Pour utiliser ce pipeline sur vos index basés sur l'API, vous devrez le référencer explicitement dans vos requêtes d'API.", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyConnectorText": "Ce pipeline s'exécute automatiquement sur tous les index Robot d'indexation et Connecteur créés via Enterprise Search.", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalHeaderTitle": "Paramètres du pipeline", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalIngestLinkLabel": "En savoir plus sur les pipelines d'ingestion Enterprise Search", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.saveButtonLabel": "Enregistrer", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.apiIndex": "Il s'agit d'un index basé sur l'API.", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.cancelButtonLabel": "Annuler", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.closeButtonLabel": "Fermer", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.copyButtonLabel": "Copier et personnaliser", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.curlHeader": "Exemple de requête cURL pour ingérer un document", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyAPITextCont": "Pour utiliser ce pipeline sur vos index basés sur l'API, vous devrez le référencer explicitement dans vos requêtes d'API.", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyConnectorText": "Ce pipeline s'exécute automatiquement sur tous les index Robot d'indexation et Connecteur créés via Enterprise Search.", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalHeaderTitle": "Paramètres du pipeline", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalIngestLinkLabel": "En savoir plus sur les pipelines d'ingestion Enterprise Search", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.saveButtonLabel": "Enregistrer", "xpack.enterpriseSearch.content.index.pipelines.settings.extractBinaryDescription": "Extraire le contenu des images et des fichiers PDF", "xpack.enterpriseSearch.content.index.pipelines.settings.extractBinaryLabel": "Extraction du contenu", "xpack.enterpriseSearch.content.index.pipelines.settings.formHeader": "Optimisez votre contenu pour la recherche", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ccd32864c7028..bb2e6af5dd6f1 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -10547,7 +10547,7 @@ "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.crawler.subheading": "現在、Webクローラーログは{minAgeDays}日間保存されています。", "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.prompt": "確認する「{target}」を入力します。", "xpack.enterpriseSearch.appSearch.sourceEngines.removeEngineConfirmDialogue.description": "エンジン'{engineName}'はこのメタエンジンから削除されます。すべての既存の設定は失われます。よろしいですか?", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyAPIText": "{apiIndex}以下の設定に行われた変更は参照専用です。これらの設定は、インデックスまたはパイプラインまで永続しません。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyAPIText": "{apiIndex}以下の設定に行われた変更は参照専用です。これらの設定は、インデックスまたはパイプラインまで永続しません。", "xpack.enterpriseSearch.content.indices.callout.text": "Elasticsearchインデックスは、現在、エンタープライズ サーチの中心です。直接そのインデックスを使用して、新しいインデックスを作成し、検索エクスペリエンスを構築できます。エンタープライズ サーチでのElasticsearchの使用方法の詳細については、{docLink}をご覧ください", "xpack.enterpriseSearch.content.indices.configurationConnector.apiKey.description": "まず、Elasticsearch APIキーを生成します。この{apiKeyName}は、コネクターがドキュメントを作成された{indexName}インデックスにインデックスするための読み書き権限を有効にします。キーは安全な場所に保管してください。コネクターを構成するときに必要になります。", "xpack.enterpriseSearch.content.indices.configurationConnector.config.description.firstParagraph": "コネクターがデプロイされたので、カスタムデータソースのデプロイ済みコネクタークライアントを強化します。{link}を参照して、データソース固有の実装ロジックを追加してください。", @@ -11595,16 +11595,16 @@ "xpack.enterpriseSearch.content.index.filtering.value": "値", "xpack.enterpriseSearch.content.index.pipelines.copyAndCustomize.description": "この構成のインデックス固有のバージョンを作成し、ユースケースに合わせて修正できます。", "xpack.enterpriseSearch.content.index.pipelines.copyAndCustomize.platinumText": "プラチナライセンスでは、この構成のインデックス固有のバージョンを作成し、ユースケースに合わせて修正できます。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.apiIndex": "これはAPIベースのインデックスです。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.cancelButtonLabel": "キャンセル", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.closeButtonLabel": "閉じる", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.copyButtonLabel": "コピーしてカスタマイズ", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.curlHeader": "ドキュメントをインジェストするサンプルcURLリクエスト", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyAPITextCont": "APIベースのインデックスでこのパイプラインを使用するには、APIリクエストで明示的にそのパイプラインを参照する必要があります。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyConnectorText": "このパイプラインは、エンタープライズ サーチで作成されたすべてのクローラーおよびコネクターインデックスで自動的に実行されます。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalHeaderTitle": "パイプライン設定", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalIngestLinkLabel": "エンタープライズ サーチインジェストパイプラインの詳細", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.saveButtonLabel": "保存", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.apiIndex": "これはAPIベースのインデックスです。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.cancelButtonLabel": "キャンセル", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.closeButtonLabel": "閉じる", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.copyButtonLabel": "コピーしてカスタマイズ", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.curlHeader": "ドキュメントをインジェストするサンプルcURLリクエスト", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyAPITextCont": "APIベースのインデックスでこのパイプラインを使用するには、APIリクエストで明示的にそのパイプラインを参照する必要があります。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyConnectorText": "このパイプラインは、エンタープライズ サーチで作成されたすべてのクローラーおよびコネクターインデックスで自動的に実行されます。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalHeaderTitle": "パイプライン設定", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalIngestLinkLabel": "エンタープライズ サーチインジェストパイプラインの詳細", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.saveButtonLabel": "保存", "xpack.enterpriseSearch.content.index.pipelines.settings.extractBinaryDescription": "画像およびPDFファイルからコンテンツを抽出", "xpack.enterpriseSearch.content.index.pipelines.settings.extractBinaryLabel": "コンテンツ抽出", "xpack.enterpriseSearch.content.index.pipelines.settings.formHeader": "検索するコンテンツを最適化", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 57f2ed771fad5..925695a5fc21b 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -10563,7 +10563,7 @@ "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.crawler.subheading": "当前您的网络爬虫日志将存储 {minAgeDays} 天。", "xpack.enterpriseSearch.appSearch.settings.logRetention.modal.prompt": "键入“{target}”以确认。", "xpack.enterpriseSearch.appSearch.sourceEngines.removeEngineConfirmDialogue.description": "这将从此元引擎中移除引擎“{engineName}”。所有现有设置将丢失。是否确定?", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyAPIText": "{apiIndex} 对以下设置所做的更改仅供参考。这些设置不会持续用于您的索引或管道。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyAPIText": "{apiIndex} 对以下设置所做的更改仅供参考。这些设置不会持续用于您的索引或管道。", "xpack.enterpriseSearch.content.indices.callout.text": "您的 Elasticsearch 索引如今在 Enterprise Search 中位于前排和中心位置。您可以创建新索引,直接通过它们构建搜索体验。有关如何在 Enterprise Search 中使用 Elasticsearch 索引的详情,{docLink}", "xpack.enterpriseSearch.content.indices.configurationConnector.apiKey.description": "首先,生成一个 Elasticsearch API 密钥。此 {apiKeyName} 密钥将为连接器启用读取和写入权限,以便将文档索引到已创建的 {indexName} 索引。请将该密钥保存到安全位置,因为您需要它来配置连接器。", "xpack.enterpriseSearch.content.indices.configurationConnector.config.description.firstParagraph": "部署连接器后,请为您的定制数据源增强已部署的连接器客户端。提供了 {link} 供您开始添加特定于数据源的实施逻辑。", @@ -11612,16 +11612,16 @@ "xpack.enterpriseSearch.content.index.filtering.value": "值", "xpack.enterpriseSearch.content.index.pipelines.copyAndCustomize.description": "您可以创建此配置的特定于索引的版本,并针对用例对其进行修改。", "xpack.enterpriseSearch.content.index.pipelines.copyAndCustomize.platinumText": "使用白金级许可证,您可以创建此配置的特定于索引的版本,并针对用例对其进行修改。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.apiIndex": "这是一个基于 API 的索引。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.cancelButtonLabel": "取消", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.closeButtonLabel": "关闭", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.copyButtonLabel": "复制并定制", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.curlHeader": "采样 cURL 请求以采集文档", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyAPITextCont": "要在基于 API 的索引上使用此管道,您需要在 API 请求中显式引用它。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalBodyConnectorText": "此管道会自动在通过 Enterprise Search 创建的所有网络爬虫和连接器索引上运行。", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalHeaderTitle": "管道设置", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.modalIngestLinkLabel": "详细了解 Enterprise Search 采集管道", - "xpack.enterpriseSearch.content.index.pipelines.ingestModal.saveButtonLabel": "保存", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.apiIndex": "这是一个基于 API 的索引。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.cancelButtonLabel": "取消", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.closeButtonLabel": "关闭", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.copyButtonLabel": "复制并定制", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.curlHeader": "采样 cURL 请求以采集文档", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyAPITextCont": "要在基于 API 的索引上使用此管道,您需要在 API 请求中显式引用它。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalBodyConnectorText": "此管道会自动在通过 Enterprise Search 创建的所有网络爬虫和连接器索引上运行。", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalHeaderTitle": "管道设置", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.modalIngestLinkLabel": "详细了解 Enterprise Search 采集管道", + "xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.saveButtonLabel": "保存", "xpack.enterpriseSearch.content.index.pipelines.settings.extractBinaryDescription": "从图像和 PDF 文件中提取内容", "xpack.enterpriseSearch.content.index.pipelines.settings.extractBinaryLabel": "内容提取", "xpack.enterpriseSearch.content.index.pipelines.settings.formHeader": "优化您的内容以进行搜索", From 09be2baedbb19ef52af30c8a82a515009fa3bb0c Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Thu, 9 Feb 2023 14:10:59 -0600 Subject: [PATCH 054/203] [skip ci] Fix labeling for Infrastructure UI (#150571) This GitHub action broke, presumably because of changes in the API. Instead of updating the GraphQL query, switch to use the project-label-assigner action like the Actionable Observability team does. --- .github/workflows/add-to-imui-project.yml | 34 ++++++++++------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/.github/workflows/add-to-imui-project.yml b/.github/workflows/add-to-imui-project.yml index 3cf120b2e81bc..0aae53b1fc256 100644 --- a/.github/workflows/add-to-imui-project.yml +++ b/.github/workflows/add-to-imui-project.yml @@ -1,31 +1,27 @@ -name: Add to Infra Monitoring UI project +name: Add to Infrastructure Observability UI project on: issues: - types: - - labeled + types: [labeled] jobs: add_to_project: + name: Add issues to project runs-on: ubuntu-latest if: | contains(github.event.issue.labels.*.name, 'Team:Infra Monitoring UI') || contains(github.event.issue.labels.*.name, 'Feature:Stack Monitoring') || contains(github.event.issue.labels.*.name, 'Feature:Logs UI') || - contains(github.event.issue.labels.*.name, 'Feature:Metrics UI') + contains(github.event.issue.labels.*.name, 'Feature:Metrics UI') || + contains(github.event.issue.labels.*.name, 'Feature:ObsHosts') steps: - - uses: octokit/graphql-action@v2.x - id: add_to_project + - name: Add + uses: richkuz/projectnext-label-assigner@1.1.0 + id: add_to_projects with: - headers: '{"GraphQL-Features": "projects_next_graphql"}' - query: | - mutation add_to_project($projectid:ID!,$contentid:ID!) { - addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { - projectNextItem { - id - } - } - } - projectid: ${{ env.PROJECT_ID }} - contentid: ${{ github.event.issue.node_id }} + config: | + [ + {"label": "Team:Infra Monitoring UI" , "projectNumber": 664} + ] env: - PROJECT_ID: "PN_kwDOAGc3Zs1EEA" - GITHUB_TOKEN: ${{ secrets.PROJECT_ASSIGNER_TOKEN }} + GRAPHQL_API_BASE: 'https://api.github.com' + PAT_TOKEN: ${{ secrets.PROJECT_ASSIGNER_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 20a9a01cef80bc547851262da84a465630c3f9c0 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Thu, 9 Feb 2023 15:12:35 -0500 Subject: [PATCH 055/203] Upgrade EUI to v74.1.0 (#150235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary `eui@74.0.1` ⏩ `eui@74.1.0` ___ ## [`74.1.0`](https://github.com/elastic/eui/releases/tag/v74.1.0) - Added new `EuiSkeletonText`, `EuiSkeletonTitle`, `EuiSkeletonCircle`, and `EuiSkeletonRectangle` components ([#6502](https://github.com/elastic/eui/pull/6502)) - Updated `EuiSuperSelect` screen reader instructions to be more specific ([#6549](https://github.com/elastic/eui/pull/6549)) - Added `error` and updated `alert` glyphs to `EuiIcon` ([#6550](https://github.com/elastic/eui/pull/6550)) - All `EuiSkeleton` components now accept an `isLoading` flag and `children`, which automatically handles conditionally rendering loading skeletons vs. loaded content (`children`) ([#6562](https://github.com/elastic/eui/pull/6562)) - All `EuiSkeleton` components now accept a `contentAriaLabel` prop, which more meaningfully describes the loaded content to screen readers ([#6562](https://github.com/elastic/eui/pull/6562)) - Updated `EuiPopover` screen reader instructions for mobile and click behaviors ([#6567](https://github.com/elastic/eui/pull/6567)) **Bug fixes** - Fixed `EuiCard` to ensure `onClick` method only runs once when `title` contains a React node ([#6551](https://github.com/elastic/eui/pull/6551)) **Deprecations** - Deprecated `EuiLoadingContent` - use `EuiSkeletonText` instead ([#6557](https://github.com/elastic/eui/pull/6557)) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 2 +- .../__snapshots__/i18n_service.test.tsx.snap | 6 +- .../src/i18n_eui_mapping.tsx | 15 +- .../__snapshots__/header_menu.test.tsx.snap | 2 +- .../__snapshots__/list_header.test.tsx.snap | 2 +- .../__snapshots__/menu_items.test.tsx.snap | 4 +- src/dev/license_checker/config.ts | 2 +- .../__snapshots__/settings.test.tsx.snap | 10 +- .../test_models/output_loading.tsx | 8 +- .../field_renderers/field_renderers.test.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 146 ++++++++++-------- .../journey_screenshot_preview.test.tsx | 3 +- ...journey_step_screenshot_container.test.tsx | 3 +- yarn.lock | 8 +- 14 files changed, 122 insertions(+), 93 deletions(-) diff --git a/package.json b/package.json index 2373249c3a9a7..0aaf633a71dfb 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.6.0-canary.3", "@elastic/ems-client": "8.4.0", - "@elastic/eui": "74.0.1", + "@elastic/eui": "74.1.0", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", diff --git a/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap index 95e15be0220bb..f0af56e9b0b55 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap +++ b/packages/core/i18n/core-i18n-browser-internal/src/__snapshots__/i18n_service.test.tsx.snap @@ -222,7 +222,7 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiPaginationButtonArrow.previousPage": "Previous page", "euiPinnableListGroup.pinExtraActionLabel": "Pin item", "euiPinnableListGroup.pinnedExtraActionLabel": "Unpin item", - "euiPopover.screenReaderAnnouncement": "You are in a dialog. To close this dialog, hit escape.", + "euiPopover.screenReaderAnnouncement": "You are in a dialog. Press Escape, or tap/click outside the dialog to close.", "euiPrettyDuration.durationRoundedToDay": [Function], "euiPrettyDuration.durationRoundedToHour": [Function], "euiPrettyDuration.durationRoundedToMinute": [Function], @@ -298,6 +298,8 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiSelectableTemplateSitewide.noResults": "No results available", "euiSelectableTemplateSitewide.onFocusBadgeGoTo": "Go to", "euiSelectableTemplateSitewide.searchPlaceholder": "Search for anything...", + "euiSkeletonLoading.loadedAriaText": [Function], + "euiSkeletonLoading.loadingAriaText": [Function], "euiStat.loadingText": "Statistic is loading", "euiStepStrings.complete": [Function], "euiStepStrings.current": [Function], @@ -321,7 +323,7 @@ exports[`#start() returns \`Context\` component 1`] = ` "euiSuggest.stateUnchanged": "State: unchanged.", "euiSuggest.stateUnsaved": "State: unsaved.", "euiSuggest.stateUnsavedTooltip": "Changes have not been saved.", - "euiSuperSelect.screenReaderAnnouncement": "You are in a form selector and must select a single option. Use the up and down keys to navigate or escape to close.", + "euiSuperSelect.screenReaderAnnouncement": "You are in a form selector and must select a single option. Use the Up and Down arrow keys to navigate or Escape to close.", "euiSuperSelectControl.selectAnOption": [Function], "euiSuperUpdateButton.cannotUpdateTooltip": "Cannot update", "euiSuperUpdateButton.clickToApplyTooltip": "Click to apply", diff --git a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx index 439e928f977e9..95d354ea2c017 100644 --- a/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx +++ b/packages/core/i18n/core-i18n-browser-internal/src/i18n_eui_mapping.tsx @@ -1019,7 +1019,8 @@ export const getEuiContextMapping = (): EuiTokensObject => { 'euiPopover.screenReaderAnnouncement': i18n.translate( 'core.euiPopover.screenReaderAnnouncement', { - defaultMessage: 'You are in a dialog. To close this dialog, hit escape.', + defaultMessage: + 'You are in a dialog. Press Escape, or tap/click outside the dialog to close.', } ), 'euiProgress.valueText': ({ value }: EuiValues) => @@ -1636,7 +1637,7 @@ export const getEuiContextMapping = (): EuiTokensObject => { 'core.euiSuperSelect.screenReaderAnnouncement', { defaultMessage: - 'You are in a form selector and must select a single option. Use the up and down keys to navigate or escape to close.', + 'You are in a form selector and must select a single option. Use the Up and Down arrow keys to navigate or Escape to close.', } ), 'euiSuperSelectControl.selectAnOption': ({ selectedValue }: EuiValues) => @@ -1777,5 +1778,15 @@ export const getEuiContextMapping = (): EuiTokensObject => { defaultMessage: '{eventName} is unread', values: { eventName }, }), + 'euiSkeletonLoading.loadingAriaText': ({ contentAriaLabel }: EuiValues) => + i18n.translate('core.euiSkeletonLoading.loadingAriaText', { + defaultMessage: 'Loading {contentAriaLabel}', + values: { contentAriaLabel }, + }), + 'euiSkeletonLoading.loadedAriaText': ({ contentAriaLabel }: EuiValues) => + i18n.translate('core.euiSkeletonLoading.loadedAriaText', { + defaultMessage: 'Loaded {contentAriaLabel}', + values: { contentAriaLabel }, + }), }; }; diff --git a/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap b/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap index 412add3e45c26..a1b31de44f1d7 100644 --- a/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap +++ b/packages/kbn-securitysolution-exception-list-components/src/header_menu/__snapshots__/header_menu.test.tsx.snap @@ -172,7 +172,7 @@ Object { class="emotion-euiScreenReaderOnly" id="generated-id" > - You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

- You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

- You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

- You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

can navigate Autoplay Settings 1`] = ` class="emotion-euiScreenReaderOnly" id="generated-id" > - You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

can navigate Autoplay Settings 2`] = ` class="emotion-euiScreenReaderOnly" id="generated-id" > - You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

can navigate Toolbar Settings, closes when activated 1`] = class="emotion-euiScreenReaderOnly" id="generated-id" > - You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

can navigate Toolbar Settings, closes when activated 2`] = class="emotion-euiScreenReaderOnly" id="generated-id" > - You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

can navigate Toolbar Settings, closes when activated 3`] = class="emotion-euiScreenReaderOnly" id="generated-id" > - You are in a dialog. To close this dialog, hit escape. + You are in a dialog. Press Escape, or tap/click outside the dialog to close.

= ({ text }) => { const actualLines = text.split(/\r\n|\r|\n/).length + 1; const lines = actualLines > 4 && actualLines <= 10 ? actualLines : 4; return ( - + ); }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx index c62c1c967771d..b08988b275094 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx @@ -427,7 +427,9 @@ describe('Field Renderers', () => { userEvent.click(screen.getByTestId('DefaultFieldRendererOverflow-button')); expect( - screen.getByText('You are in a dialog. To close this dialog, hit escape.') + screen.getByText( + 'You are in a dialog. Press Escape, or tap/click outside the dialog to close.' + ) ).toBeInTheDocument(); expect(screen.getByTestId('more-container').textContent).toEqual('item6item7'); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/side_panel/__snapshots__/index.test.tsx.snap index 5763637266e2d..9717daac79baf 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/__snapshots__/index.test.tsx.snap @@ -66,42 +66,47 @@ Array [
, - - - - - - - - - - - , + aria-label="Loading " + class="euiSkeletonText" + role="progressbar" + > + + + + + + + + + + + +
,
- - - - - - - - - - - + aria-label="Loading " + class="euiSkeletonText" + role="progressbar" + > + + + + + + + + + + + +
diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/journey_screenshot_preview.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/journey_screenshot_preview.test.tsx index 940f025f6dbe0..cedf240b36115 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/journey_screenshot_preview.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/monitor_test_result/journey_screenshot_preview.test.tsx @@ -76,7 +76,8 @@ describe('JourneyScreenshotPreview', () => { ); const img = getByAltText('First step'); - const euiPopoverMessage = 'You are in a dialog. To close this dialog, hit escape.'; // Helps to detect if popover is open + const euiPopoverMessage = + 'You are in a dialog. Press Escape, or tap/click outside the dialog to close.'; // Helps to detect if popover is open expect(queryByText(euiPopoverMessage)).toBeNull(); fireEvent.mouseEnter(img); await waitFor(() => getByText(euiPopoverMessage)); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/screenshot/journey_step_screenshot_container.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/screenshot/journey_step_screenshot_container.test.tsx index 41824c22a5ce1..fc194af26038c 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/screenshot/journey_step_screenshot_container.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/screenshot/journey_step_screenshot_container.test.tsx @@ -83,7 +83,8 @@ describe('JourneyStepScreenshotContainer', () => { ); const img = getByAltText('First step'); - const euiPopoverMessage = 'You are in a dialog. To close this dialog, hit escape.'; + const euiPopoverMessage = + 'You are in a dialog. Press Escape, or tap/click outside the dialog to close.'; expect(queryByText(euiPopoverMessage)).toBeNull(); fireEvent.mouseEnter(img); await waitFor(() => getByText(euiPopoverMessage)); diff --git a/yarn.lock b/yarn.lock index 8485c0376b5e3..c5a662bdf9bd2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1539,10 +1539,10 @@ resolved "https://registry.yarnpkg.com/@elastic/eslint-plugin-eui/-/eslint-plugin-eui-0.0.2.tgz#56b9ef03984a05cc213772ae3713ea8ef47b0314" integrity sha512-IoxURM5zraoQ7C8f+mJb9HYSENiZGgRVcG4tLQxE61yHNNRDXtGDWTZh8N1KIHcsqN1CEPETjuzBXkJYF/fDiQ== -"@elastic/eui@74.0.1": - version "74.0.1" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-74.0.1.tgz#4397d9d5308f9da7abcf66a376bf87fd6f33af7f" - integrity sha512-vaaysWN/CzzMXvt8bGnwHXLPbMgeN7qNUo+mYdqda7aHo2BPvlapmtZmf3L3cIX1m9bxQW/dcuSLLQ5Wcx3fTA== +"@elastic/eui@74.1.0": + version "74.1.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-74.1.0.tgz#bf60ad199715da3622deb33efb587893a9321073" + integrity sha512-pSoIO7h/T4gR3yZbKcadSt8/pPNb45L6s8mR5nHLDo+otAam6Yo3V1u9Upwc5QOVW82hROPfvao44lY7egIiAw== dependencies: "@types/chroma-js" "^2.0.0" "@types/lodash" "^4.14.160" From 216fb3a1806d67c35e7ee84353d4d6460f87ad85 Mon Sep 17 00:00:00 2001 From: Davis Plumlee <56367316+dplumlee@users.noreply.github.com> Date: Thu, 9 Feb 2023 16:00:07 -0500 Subject: [PATCH 056/203] [Security Solution] Fixes bulk close alerts from exception flyout type bug (#150765) --- .../rule_exceptions/utils/helpers.test.tsx | 10 ++++++++++ .../detection_engine/rule_exceptions/utils/helpers.tsx | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.test.tsx index d3875415c49c7..97a6a00c9cf0a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.test.tsx @@ -384,6 +384,16 @@ describe('Exception helpers', () => { const result = prepareExceptionItemsForBulkClose(payload); expect(result).toEqual(expected); }); + + test("should strip out any comments in the exceptions for bulk close'", () => { + const exceptionItemWithComment = { + ...getExceptionListItemSchemaMock(), + comments: getCommentsArrayMock(), + }; + const payload = [exceptionItemWithComment]; + const result = prepareExceptionItemsForBulkClose(payload); + expect(result).toEqual([getExceptionListItemSchemaMock()]); + }); }); describe('#lowercaseHashValues', () => { diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx index 6a739fd34a05a..aaaffb0e70d2c 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/utils/helpers.tsx @@ -154,9 +154,10 @@ export const prepareExceptionItemsForBulkClose = ( return { ...item, entries: newEntries, + comments: [], // Strips out unneeded comments attribute for bulk close as they are not needed and are throwing type errors }; } else { - return item; + return { ...item, comments: [] }; } }); }; From 576c92ce7fc7521f7059e24a54ffbec8156f4668 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Thu, 9 Feb 2023 16:34:05 -0500 Subject: [PATCH 057/203] [Synthetics] adjust overview scrolling e2e (#150774) ## Summary Adjusts the scrolling mechanism for synthetics scrolling test. --- .../e2e/journeys/synthetics/overview_scrolling.journey.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts index 829223dabfe70..c592595e15eaf 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/overview_scrolling.journey.ts @@ -56,7 +56,7 @@ journey('OverviewScrolling', async ({ page, params }) => { expect(count <= 32).toBe(true); await retry.tryForTime(90 * 1000, async () => { - await page.mouse.wheel(0, 100); + await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); const showingAllMonitorsNode = await page.$(`text="Showing all monitors"`); expect(showingAllMonitorsNode).toBeTruthy(); expect(await showingAllMonitorsNode?.isVisible()).toBe(true); From d6a4ebf46d9af18618cfed16666921b58db1e400 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 9 Feb 2023 14:35:28 -0700 Subject: [PATCH 058/203] fixes Failing ES Promotion: X-Pack API Integration Tests x-pack/test/api_integration/apis/maps/get_grid_tile.js (#150768) Fixes https://github.com/elastic/kibana/issues/149068 Order of the vertices changed as side effect of https://github.com/elastic/elasticsearch/pull/92883. PR updates expects clause for new order --- x-pack/test/api_integration/apis/maps/get_grid_tile.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index 0b3a454da814c..841c795a0d9a2 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -21,8 +21,7 @@ function findFeature(layer, callbackFn) { export default function ({ getService }) { const supertest = getService('supertest'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/149068 - describe.skip('getGridTile', () => { + describe('getGridTile', () => { const URL = `/api/maps/mvt/getGridTile/3/2/3.pbf\ ?geometryFieldName=geo.coordinates\ &hasLabels=false\ @@ -152,13 +151,13 @@ export default function ({ getService }) { // assert feature geometry is hex expect(gridFeature.loadGeometry()).to.eql([ [ - { x: 111, y: 698 }, { x: 89, y: 710 }, { x: 67, y: 696 }, { x: 67, y: 669 }, { x: 89, y: 657 }, { x: 112, y: 672 }, { x: 111, y: 698 }, + { x: 89, y: 710 }, ], ]); }); From 62116bfe2287df1907d86a543ff46d917438f373 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 9 Feb 2023 14:35:57 -0700 Subject: [PATCH 059/203] [maps] fix Changing resolutions on Heat map layer throws error in console (#150761) Fixes https://github.com/elastic/kibana/issues/150711 --- .../classes/sources/es_geo_grid_source/es_geo_grid_source.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx index 7102978602e90..dea665f904b01 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx @@ -98,7 +98,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo const resolutionPropChange = sourceChanges.find((sourceChange) => { return sourceChange.propName === 'resolution'; }); - if (resolutionPropChange) { + if (resolutionPropChange && 'getPropertiesDescriptor' in sourceEditorArgs.style) { const propertiesDescriptor = ( sourceEditorArgs.style as VectorStyle ).getPropertiesDescriptor(); From e7209f52a91170ce3e53d2bd27bafaecf6195d54 Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Thu, 9 Feb 2023 16:41:15 -0500 Subject: [PATCH 060/203] [Fleet] Fix max 20 installed integrations returned from Fleet API (#150780) ## Summary Fix an (old) bug where Fleet's "list packages" API endpoint would only ever return 20 installed integrations at most. I haven't included a test case here because I'm not sure we have 20 test packages that can reasonably be installed at the same time. Also feels like an arbitrary number to introduce a "lists all packages even if there are more N" test case. Open to feedback on testing. ## Before 23 installed integrations, only 20 in UI ![image](https://user-images.githubusercontent.com/6766512/217930020-f6dafe56-191a-48c0-acb4-c567810a6dad.png) ![image](https://user-images.githubusercontent.com/6766512/217930126-441e78a8-d484-4c5d-b5df-00179d930e4a.png) ## After 23 installed integrations, 23 in UI ![image](https://user-images.githubusercontent.com/6766512/217930384-21506d77-7244-42c1-93bd-97025a8ec86e.png) --- x-pack/plugins/fleet/server/services/epm/packages/get.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts index 1d048e2cf2d2c..83db878ef5b83 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.ts @@ -12,6 +12,7 @@ import type { Logger } from '@kbn/core/server'; import { installationStatuses, PACKAGE_POLICY_SAVED_OBJECT_TYPE, + SO_SEARCH_LIMIT, } from '../../../../common/constants'; import { isPackageLimited } from '../../../../common/services'; import type { @@ -137,6 +138,7 @@ export async function getPackageSavedObjects( return savedObjectsClient.find({ ...(options || {}), type: PACKAGES_SAVED_OBJECT_TYPE, + perPage: SO_SEARCH_LIMIT, }); } From 902ef9ea73c45619823c460f1e6dcd83bd896d45 Mon Sep 17 00:00:00 2001 From: Katie Hughes Date: Thu, 9 Feb 2023 14:04:50 -0800 Subject: [PATCH 061/203] [docs] Remove kibDevDocsOpsPluginDiscovery (#150788) ## Summary This page id no longer exists, so our build is breaking. If you have a better solution, please update this PR! ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- dev_docs/operations/operations_landing.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/dev_docs/operations/operations_landing.mdx b/dev_docs/operations/operations_landing.mdx index 37a240a599d2e..e38999f8d1046 100644 --- a/dev_docs/operations/operations_landing.mdx +++ b/dev_docs/operations/operations_landing.mdx @@ -38,7 +38,6 @@ layout: landing { pageId: "kibDevDocsOpsBabelPreset" }, { pageId: "kibDevDocsOpsUiSharedDepsNpm" }, { pageId: "kibDevDocsOpsUiSharedDepsSrc" }, - { pageId: "kibDevDocsOpsPluginDiscovery" }, ]} /> From b53d48348c20fd83d15eb6fb17977e16c1f7699e Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 9 Feb 2023 16:29:26 -0700 Subject: [PATCH 062/203] [codeowners] allow overrides to take higher precedence (#150821) With #149344 the codeowners has many more entries in it, and these entries are taking precedence because in codeowner files: https://help.github.com/articles/about-codeowners/ > Order is important; the last matching pattern takes the most precedence. This reverses the order of the codeowners file, placing all of the auto-generated codeowners at the top of the file, followed by the manually managed overrides, and finally followed by the "ultimate priority" rules which gives design codeowners over all .scss files in the repo. --- .github/CODEOWNERS | 1023 +++++++++-------- .../src/commands/codeowners_command.ts | 78 +- 2 files changed, 550 insertions(+), 551 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4feac718f908d..6017050be748a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,509 +1,8 @@ -# GitHub CODEOWNERS definition -# Identify which groups will be pinged by changes to different parts of the codebase. -# For more info, see https://help.github.com/articles/about-codeowners/ - -# The #CC# prefix delineates Code Coverage, -# used for the 'team' designator within Kibana Stats - -# Data Discovery -/x-pack/test/functional/apps/discover/ @elastic/kibana-data-discovery -/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/discover/ @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/test/search_sessions_integration/ @elastic/kibana-data-discovery -/test/plugin_functional/test_suites/data_plugin @elastic/kibana-data-discovery -/examples/demo_search/ @elastic/kibana-data-discovery - -# Vis Editors -/src/plugins/visualize/ @elastic/kibana-visualizations -/x-pack/test/functional/apps/lens @elastic/kibana-visualizations -/x-pack/test/api_integration/apis/lens/ @elastic/kibana-visualizations -/test/functional/apps/visualize/ @elastic/kibana-visualizations -/x-pack/test/functional/apps/graph @elastic/kibana-visualizations - -# Global Experience - -### Global Experience Reporting -/x-pack/test/functional/apps/dashboard/reporting/ @elastic/appex-sharedux -/x-pack/test/functional/apps/reporting/ @elastic/appex-sharedux -/x-pack/test/functional/apps/reporting_management/ @elastic/appex-sharedux -/x-pack/test/examples/screenshotting/ @elastic/appex-sharedux -/x-pack/test/functional/es_archives/lens/reporting/ @elastic/appex-sharedux -/x-pack/test/functional/es_archives/reporting/ @elastic/appex-sharedux -/x-pack/test/functional/fixtures/kbn_archiver/reporting/ @elastic/appex-sharedux -/x-pack/test/reporting_api_integration/ @elastic/appex-sharedux -/x-pack/test/reporting_functional/ @elastic/appex-sharedux -/x-pack/test/stack_functional_integration/apps/reporting/ @elastic/appex-sharedux -/docs/user/reporting @elastic/appex-sharedux -/docs/settings/reporting-settings.asciidoc @elastic/appex-sharedux -/docs/setup/configuring-reporting.asciidoc @elastic/appex-sharedux - -### Global Experience Tagging -/x-pack/test/saved_object_tagging/ @elastic/appex-sharedux - -### Kibana React (to be deprecated) -/src/plugins/kibana_react/public/@elastic/appex-sharedux @elastic/kibana-presentation - -### Home Plugin and Packages -/src/plugins/home/public @elastic/appex-sharedux -/src/plugins/home/server/*.ts @elastic/appex-sharedux -/src/plugins/home/server/services/ @elastic/appex-sharedux - -### Code Coverage -#CC# /src/plugins/home/public @elastic/appex-sharedux -#CC# /src/plugins/home/server/services/ @elastic/appex-sharedux -#CC# /src/plugins/home/ @elastic/appex-sharedux -#CC# /x-pack/plugins/reporting/ @elastic/appex-sharedux - -### Observability Plugins - -# Observability Shared -/x-pack/plugins/observability/public/components/shared/date_picker/ @elastic/uptime - -# 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 -/x-pack/plugins/observability/public/pages/landing @elastic/observability-design -/x-pack/plugins/observability/public/pages/overview @elastic/observability-design @elastic/actionable-observability - -# Actionable Observability -/x-pack/plugins/observability/common/rules @elastic/actionable-observability -/x-pack/plugins/observability/public/rules @elastic/actionable-observability -/x-pack/plugins/observability/public/pages/alerts @elastic/actionable-observability -/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 - -# Infra Monitoring -/x-pack/test/functional/apps/infra @elastic/infra-monitoring-ui -/x-pack/test/api_integration/apis/infra @elastic/infra-monitoring-ui - -# Elastic Stack Monitoring -/x-pack/test/functional/apps/monitoring @elastic/infra-monitoring-ui -/x-pack/test/api_integration/apis/monitoring @elastic/infra-monitoring-ui -/x-pack/test/api_integration/apis/monitoring_collection @elastic/infra-monitoring-ui - -# Fleet -/fleet_packages.json @elastic/fleet -/x-pack/test/fleet_api_integration @elastic/fleet -/x-pack/test/fleet_cypress @elastic/fleet -/x-pack/test/fleet_functional @elastic/fleet -/src/dev/build/tasks/bundle_fleet_packages.ts @elastic/fleet @elastic/kibana-operations - -# APM -/x-pack/test/functional/apps/apm/ @elastic/apm-ui -/x-pack/test/apm_api_integration/ @elastic/apm-ui -/src/apm.js @elastic/kibana-core @vigneshshanmugam -/src/core/types/elasticsearch @elastic/apm-ui -/packages/kbn-utility-types/src/dot.ts @dgieselaar -/packages/kbn-utility-types/src/dot_test.ts @dgieselaar -#CC# /src/plugins/apm_oss/ @elastic/apm-ui -#CC# /x-pack/plugins/observability/ @elastic/apm-ui - -# Uptime -/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/ @elastic/uptime -/x-pack/test/functional/apps/uptime @elastic/uptime -/x-pack/test/functional/es_archives/uptime @elastic/uptime -/x-pack/test/functional/services/uptime @elastic/uptime -/x-pack/test/api_integration/apis/uptime @elastic/uptime -/x-pack/plugins/observability/public/components/shared/exploratory_view @elastic/uptime - - -# Client Side Monitoring / Uptime (lives in APM directories but owned by Uptime) -/x-pack/plugins/apm/public/application/uxApp.tsx @elastic/uptime -/x-pack/plugins/apm/public/components/app/rum_dashboard @elastic/uptime -/x-pack/test/apm_api_integration/tests/csm/ @elastic/uptime - -# Observability onboarding tour -/x-pack/plugins/observability/public/components/shared/tour @elastic/platform-onboarding -/x-pack/test/functional/apps/infra/tour.ts @elastic/platform-onboarding - -### END Observability Plugins - -# Presentation -/test/functional/apps/dashboard/ @elastic/kibana-presentation -/test/functional/apps/dashboard_elements/ @elastic/kibana-presentation -/test/functional/services/dashboard/ @elastic/kibana-presentation -/x-pack/test/functional/apps/canvas/ @elastic/kibana-presentation -/test/plugin_functional/test_suites/panel_actions @elastic/kibana-presentation -#CC# /src/plugins/kibana_react/public/code_editor/ @elastic/kibana-presentation - -# Machine Learning -/x-pack/plugins/ml/common/openapi/ @elastic/mlr-docs -/x-pack/test/accessibility/apps/ml.ts @elastic/ml-ui -/x-pack/test/accessibility/apps/ml_embeddables_in_dashboard.ts @elastic/ml-ui -/x-pack/test/api_integration/apis/ml/ @elastic/ml-ui -/x-pack/test/api_integration_basic/apis/ml/ @elastic/ml-ui -/x-pack/test/functional/apps/ml/ @elastic/ml-ui -/x-pack/test/functional/es_archives/ml/ @elastic/ml-ui -/x-pack/test/functional/services/ml/ @elastic/ml-ui -/x-pack/test/functional_basic/apps/ml/ @elastic/ml-ui -/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/ @elastic/ml-ui -/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/ml_rule_types/ @elastic/ml-ui -/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/ @elastic/ml-ui -/x-pack/test/screenshot_creation/apps/ml_docs @elastic/ml-ui -/x-pack/test/screenshot_creation/services/ml_screenshots.ts @elastic/ml-ui -/docs/api/machine-learning/ @elastic/mlr-docs - -# Additional plugins and packages maintained by the ML team. -/x-pack/test/accessibility/apps/transform.ts @elastic/ml-ui -/x-pack/test/api_integration/apis/transform/ @elastic/ml-ui -/x-pack/test/api_integration_basic/apis/transform/ @elastic/ml-ui -/x-pack/test/functional/apps/transform/ @elastic/ml-ui -/x-pack/test/functional/services/transform/ @elastic/ml-ui -/x-pack/test/functional_basic/apps/transform/ @elastic/ml-ui - -# Maps -#CC# /x-pack/plugins/maps/ @elastic/kibana-gis -/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/plugins/stack_alerts/server/rule_types/geo_containment @elastic/kibana-gis -/x-pack/plugins/stack_alerts/public/rule_types/geo_containment @elastic/kibana-gis -#CC# /x-pack/plugins/file_upload @elastic/kibana-gis - -# Operations -/src/dev/license_checker/config.ts @elastic/kibana-operations -/src/dev/ @elastic/kibana-operations -/src/setup_node_env/ @elastic/kibana-operations -/src/cli/keystore/ @elastic/kibana-operations -/.ci/es-snapshots/ @elastic/kibana-operations -/.github/workflows/ @elastic/kibana-operations -/vars/ @elastic/kibana-operations -/.bazelignore @elastic/kibana-operations -/.bazeliskversion @elastic/kibana-operations -/.bazelrc @elastic/kibana-operations -/.bazelrc.common @elastic/kibana-operations -/.bazelversion @elastic/kibana-operations -/WORKSPACE.bazel @elastic/kibana-operations -/.buildkite/ @elastic/kibana-operations -/kbn_pm/ @elastic/kibana-operations - -# Quality Assurance -/src/dev/code_coverage @elastic/kibana-qa -/vars/*Coverage.groovy @elastic/kibana-qa -/test/functional/services/common @elastic/kibana-qa -/test/functional/services/lib @elastic/kibana-qa -/test/functional/services/remote @elastic/kibana-qa -/test/visual_regression @elastic/kibana-qa -/x-pack/test/visual_regression @elastic/kibana-qa - -# Core -/config/kibana.yml @elastic/kibana-core -/typings/ @elastic/kibana-core -/x-pack/test/saved_objects_field_count/ @elastic/kibana-core -/test/analytics @elastic/kibana-core -#CC# /src/core/server/csp/ @elastic/kibana-core -#CC# /src/plugins/saved_objects/ @elastic/kibana-core -#CC# /x-pack/plugins/cloud/ @elastic/kibana-core -#CC# /x-pack/plugins/features/ @elastic/kibana-core -#CC# /x-pack/plugins/global_search/ @elastic/kibana-core -#CC# /src/plugins/newsfeed @elastic/kibana-core -#CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core - -# Kibana Telemetry -/.telemetryrc.json @elastic/kibana-core -/x-pack/.telemetryrc.json @elastic/kibana-core -/src/plugins/telemetry/schema/ @elastic/kibana-core @elastic/kibana-telemetry -/x-pack/plugins/telemetry_collection_xpack/schema/ @elastic/kibana-core @elastic/kibana-telemetry - -# Kibana Localization -/src/dev/i18n/ @elastic/kibana-localization @elastic/kibana-core -/src/core/public/i18n/ @elastic/kibana-localization @elastic/kibana-core -#CC# /x-pack/plugins/translations/ @elastic/kibana-localization @elastic/kibana-core - -# Kibana Platform Security -/src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security -/test/interactive_setup_api_integration/ @elastic/kibana-security -/test/interactive_setup_functional/ @elastic/kibana-security -/test/plugin_functional/test_suites/core_plugins/rendering.ts @elastic/kibana-security -/x-pack/test/api_integration/apis/security/ @elastic/kibana-security -/x-pack/test/api_integration/apis/spaces/ @elastic/kibana-security -/x-pack/test/ui_capabilities/ @elastic/kibana-security -/x-pack/test/encrypted_saved_objects_api_integration/ @elastic/kibana-security -/x-pack/test/functional/apps/security/ @elastic/kibana-security -/x-pack/test/functional/apps/spaces/ @elastic/kibana-security -/x-pack/test/security_api_integration/ @elastic/kibana-security -/x-pack/test/security_functional/ @elastic/kibana-security -/x-pack/test/spaces_api_integration/ @elastic/kibana-security -/x-pack/test/saved_object_api_integration/ @elastic/kibana-security -#CC# /x-pack/plugins/security/ @elastic/kibana-security - -# Response Ops team -/x-pack/test/alerting_api_integration/ @elastic/response-ops -/x-pack/test/plugin_api_integration/test_suites/task_manager/ @elastic/response-ops -/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/response-ops -/docs/user/alerting/ @elastic/response-ops -/docs/management/connectors/ @elastic/response-ops -/x-pack/test/cases_api_integration/ @elastic/response-ops -/x-pack/test/functional/services/cases/ @elastic/response-ops -/x-pack/test/functional_with_es_ssl/apps/cases/ @elastic/response-ops -/x-pack/test/api_integration/apis/cases/ @elastic/response-ops -/docs/api/actions-and-connectors @elastic/mlr-docs -/docs/api/alerting @elastic/mlr-docs -/docs/api/cases @elastic/mlr-docs -/x-pack/plugins/cases/docs/openapi @elastic/mlr-docs - -# Enterprise Search -/x-pack/test/functional_enterprise_search/ @elastic/enterprise-search-frontend -/x-pack/plugins/enterprise_search/public/applications/shared/doc_links @elastic/ent-search-docs-team - -# Management Experience - Deployment Management -#CC# /x-pack/plugins/cross_cluster_replication/ @elastic/platform-deployment-management - -# Security Solution -/x-pack/test/endpoint_api_integration_no_ingest/ @elastic/security-solution -/x-pack/test/security_solution_endpoint/ @elastic/security-solution -/x-pack/test/functional/es_archives/endpoint/ @elastic/security-solution -/x-pack/test/plugin_functional/test_suites/resolver/ @elastic/security-solution -/x-pack/test/detection_engine_api_integration @elastic/security-solution -/x-pack/test/lists_api_integration @elastic/security-solution -/x-pack/test/api_integration/apis/security_solution @elastic/security-solution -#CC# /x-pack/plugins/security_solution/ @elastic/security-solution - -# Security Solution sub teams - -## Security Solution sub teams - Threat Hunting Investigations - -/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/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 -/x-pack/plugins/security_solution/public/common/components/event_details @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/common/components/events_viewer @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/common/components/markdown_editor @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/detections/components/alerts_kpis @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/detections/components/alerts_table @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/detections/components/alerts_info @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/resolver @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/public/timelines @elastic/security-threat-hunting-investigations - -/x-pack/plugins/security_solution/server/lib/timeline @elastic/security-threat-hunting-investigations - -## Security Solution sub teams - Threat Hunting Explore -/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram @elastic/security-threat-hunting-explore -/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/e2e/cases @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/e2e/filters @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_e2e/threat_hunting/cases @elastic/security-threat-hunting-explore - -/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour @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 -/x-pack/plugins/security_solution/public/common/components/header_section @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/inspect @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/last_event_time @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/links @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/matrix_histogram @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/navigation @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/news_feed @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/overview_description_list @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/page @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/sidebar_header @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/tables @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/top_n @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/components/with_hover_actions @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/containers/matrix_histogram @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/common/lib/cell_actions @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/cases @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/explore @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/public/overview @elastic/security-threat-hunting-explore - -/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users @elastic/security-threat-hunting-explore - -## Security Solution sub teams - Detections and Response Alerts -/x-pack/plugins/security_solution/common/detection_engine/schemas/alerts @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/common/field_maps @elastic/security-detections-response-alerts - -/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/public/detections/pages/alerts @elastic/security-detections-response-alerts - -/x-pack/plugins/security_solution/server/lib/detection_engine/migrations @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/server/lib/detection_engine/signals @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals @elastic/security-detections-response-alerts - -## Security Solution sub teams - Detections and Response Rules -/x-pack/plugins/security_solution/common/detection_engine/fleet_integrations @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/common/detection_engine/prebuilt_rules @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/common/detection_engine/rule_management @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/common/detection_engine/rule_monitoring @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/common/detection_engine/rule_schema @elastic/security-detections-response-rules @elastic/security-detections-response-alerts - -/x-pack/plugins/security_solution/public/common/components/health_truncate_text @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/common/components/links_to_docs @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/common/components/ml_popover @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/common/components/popover_items @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detection_engine/fleet_integrations @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detection_engine/rule_management @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detections/components/callouts @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal @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/rules/rule_preview @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detections/mitre @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/public/rules @elastic/security-detections-response-rules - -/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema @elastic/security-detections-response-rules @elastic/security-detections-response-alerts - -/x-pack/plugins/security_solution/server/utils @elastic/security-detections-response-rules - -## Security Solution sub teams - Security 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/common/detection_engine/rule_exceptions @elastic/security-solution-platform - -/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions @elastic/security-solution-platform -/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions_ui @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 -/x-pack/plugins/security_solution/public/detections/containers/detection_engine/lists @elastic/security-solution-platform -/x-pack/plugins/security_solution/public/common/components/sourcerer @elastic/security-solution-platform - -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy @elastic/security-solution-platform -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions @elastic/security-solution-platform -/x-pack/plugins/security_solution/server/lib/sourcerer @elastic/security-solution-platform - -## Security Threat Intelligence - Under Security Platform -/x-pack/plugins/security_solution/public/common/components/threat_match @elastic/security-solution-platform - -## Security Solution cross teams ownership -/x-pack/plugins/security_solution/cypress/fixtures @elastic/security-detections-response @elastic/security-threat-hunting -/x-pack/plugins/security_solution/cypress/helpers @elastic/security-detections-response @elastic/security-threat-hunting -/x-pack/plugins/security_solution/cypress/e2e/detection_rules @elastic/security-detections-response-rules @elastic/security-detections-response-alerts -/x-pack/plugins/security_solution/cypress/objects @elastic/security-detections-response @elastic/security-threat-hunting -/x-pack/plugins/security_solution/cypress/plugins @elastic/security-detections-response @elastic/security-threat-hunting -/x-pack/plugins/security_solution/cypress/screens/common @elastic/security-detections-response @elastic/security-threat-hunting -/x-pack/plugins/security_solution/cypress/support @elastic/security-detections-response @elastic/security-threat-hunting -/x-pack/plugins/security_solution/cypress/urls @elastic/security-threat-hunting-investigations @elastic/security-solution-platform - -/x-pack/plugins/security_solution/common/ecs @elastic/security-threat-hunting-investigations -/x-pack/plugins/security_solution/common/test @elastic/security-detections-response-rules @elastic/security-detections-response-alerts - -/x-pack/plugins/security_solution/public/common/components/callouts @elastic/security-detections-response -/x-pack/plugins/security_solution/public/common/components/hover_actions @elastic/security-threat-hunting-explore @elastic/security-threat-hunting-investigations - -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions @elastic/security-solution-platform @elastic/security-detections-response-rules -/x-pack/plugins/security_solution/server/routes @elastic/security-detections-response @elastic/security-threat-hunting - -## Security Solution sub teams - security-defend-workflows -/x-pack/plugins/security_solution/public/management/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/public/common/lib/endpoint*/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/public/common/components/endpoint/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/common/endpoint/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/server/endpoint/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/server/lists_integration/endpoint/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/server/lib/license/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/server/fleet_integration/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/scripts/endpoint/event_filters/ @elastic/security-defend-workflows -/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/ @elastic/security-defend-workflows -/x-pack/test/security_solution_endpoint/apps/endpoint/ @elastic/security-defend-workflows -/x-pack/test/security_solution_endpoint_api_int/ @elastic/security-defend-workflows - -## Security Solution sub teams - security-telemetry (Data Engineering) -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_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 - -## Security Solution sub teams - adaptive-workload-protection -x-pack/plugins/security_solution/public/common/components/sessions_viewer @elastic/awp-viz -x-pack/plugins/security_solution/public/kubernetes @elastic/awp-viz - -## Security Solution sub teams - Protections Experience -x-pack/plugins/security_solution/public/threat_intelligence @elastic/protections-experience -x-pack/test/threat_intelligence_cypress @elastic/protections-experience - -# Security Defend Workflows - OSQuery Ownership -/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions @elastic/security-defend-workflows -/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions @elastic/security-defend-workflows -/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions @elastic/security-defend-workflows - -# Cloud Security Posture -/x-pack/plugins/security_solution/public/cloud_security_posture @elastic/kibana-cloud-security-posture -/x-pack/test/api_integration/apis/cloud_security_posture/ @elastic/kibana-cloud-security-posture -/x-pack/test/cloud_security_posture_functional/ @elastic/kibana-cloud-security-posture - - -# Security Solution onboarding tour -/x-pack/plugins/security_solution/public/common/components/guided_onboarding @elastic/security-threat-hunting-explore -/x-pack/plugins/security_solution/cypress/e2e/guided_onboarding @elastic/security-threat-hunting-explore - -# Design (at the bottom for specificity of SASS files) -**/*.scss @elastic/kibana-design - -# Observability design -/x-pack/plugins/apm/**/*.scss @elastic/observability-design -/x-pack/plugins/infra/**/*.scss @elastic/observability-design -/x-pack/plugins/fleet/**/*.scss @elastic/observability-design -/x-pack/plugins/observability/**/*.scss @elastic/observability-design -/x-pack/plugins/monitoring/**/*.scss @elastic/observability-design - -# Ent. Search design -/x-pack/plugins/enterprise_search/**/*.scss @elastic/ent-search-design - -# Security design -/x-pack/plugins/endpoint/**/*.scss @elastic/security-design -/x-pack/plugins/security_solution/**/*.scss @elastic/security-design - -# Logstash -#CC# /x-pack/plugins/logstash/ @elastic/logstash - -# EUI design -/src/plugins/kibana_react/public/page_template/ @elastic/eui-design @elastic/appex-sharedux - -# Landing page for guided onboarding in Home plugin -/src/plugins/home/public/application/components/guided_onboarding @elastic/platform-onboarding - #### -## Everything below this comment is automatically generated based on kibana.jsonc -## "owner" fields. This file is automatically updated by CI or can be updated locally -## by running `node scripts/generate codeowners`. +## Everything at the top of the codeowners file is auto generated based on the +## "owner" fields in the kibana.jsonc files at the root of each package. This +## file is automatically updated by CI or can be updated locally by running +## `node scripts/generate codeowners`. #### x-pack/test/alerting_api_integration/common/plugins/aad @elastic/response-ops @@ -1188,9 +687,523 @@ x-pack/plugins/watcher @elastic/platform-deployment-management packages/kbn-web-worker-stub @elastic/kibana-operations packages/kbn-whereis-pkg-cli @elastic/kibana-operations packages/kbn-yarn-lock-validator @elastic/kibana-operations +#### +## Everything below this line overrides the default assignments for each package. +## Items lower in the file have higher precedence: +## https://help.github.com/articles/about-codeowners/ +#### + +# The #CC# prefix delineates Code Coverage, +# used for the 'team' designator within Kibana Stats + +# Data Discovery +/x-pack/test/functional/apps/discover/ @elastic/kibana-data-discovery +/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/discover/ @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/test/search_sessions_integration/ @elastic/kibana-data-discovery +/test/plugin_functional/test_suites/data_plugin @elastic/kibana-data-discovery +/examples/demo_search/ @elastic/kibana-data-discovery + +# Vis Editors +/src/plugins/visualize/ @elastic/kibana-visualizations +/x-pack/test/functional/apps/lens @elastic/kibana-visualizations +/x-pack/test/api_integration/apis/lens/ @elastic/kibana-visualizations +/test/functional/apps/visualize/ @elastic/kibana-visualizations +/x-pack/test/functional/apps/graph @elastic/kibana-visualizations + +# Global Experience + +### Global Experience Reporting +/x-pack/test/functional/apps/dashboard/reporting/ @elastic/appex-sharedux +/x-pack/test/functional/apps/reporting/ @elastic/appex-sharedux +/x-pack/test/functional/apps/reporting_management/ @elastic/appex-sharedux +/x-pack/test/examples/screenshotting/ @elastic/appex-sharedux +/x-pack/test/functional/es_archives/lens/reporting/ @elastic/appex-sharedux +/x-pack/test/functional/es_archives/reporting/ @elastic/appex-sharedux +/x-pack/test/functional/fixtures/kbn_archiver/reporting/ @elastic/appex-sharedux +/x-pack/test/reporting_api_integration/ @elastic/appex-sharedux +/x-pack/test/reporting_functional/ @elastic/appex-sharedux +/x-pack/test/stack_functional_integration/apps/reporting/ @elastic/appex-sharedux +/docs/user/reporting @elastic/appex-sharedux +/docs/settings/reporting-settings.asciidoc @elastic/appex-sharedux +/docs/setup/configuring-reporting.asciidoc @elastic/appex-sharedux + +### Global Experience Tagging +/x-pack/test/saved_object_tagging/ @elastic/appex-sharedux + +### Kibana React (to be deprecated) +/src/plugins/kibana_react/public/@elastic/appex-sharedux @elastic/kibana-presentation + +### Home Plugin and Packages +/src/plugins/home/public @elastic/appex-sharedux +/src/plugins/home/server/*.ts @elastic/appex-sharedux +/src/plugins/home/server/services/ @elastic/appex-sharedux + +### Code Coverage +#CC# /src/plugins/home/public @elastic/appex-sharedux +#CC# /src/plugins/home/server/services/ @elastic/appex-sharedux +#CC# /src/plugins/home/ @elastic/appex-sharedux +#CC# /x-pack/plugins/reporting/ @elastic/appex-sharedux + +### Observability Plugins + +# Observability Shared +/x-pack/plugins/observability/public/components/shared/date_picker/ @elastic/uptime + +# 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 +/x-pack/plugins/observability/public/pages/landing @elastic/observability-design +/x-pack/plugins/observability/public/pages/overview @elastic/observability-design @elastic/actionable-observability + +# Actionable Observability +/x-pack/plugins/observability/common/rules @elastic/actionable-observability +/x-pack/plugins/observability/public/rules @elastic/actionable-observability +/x-pack/plugins/observability/public/pages/alerts @elastic/actionable-observability +/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 + +# Infra Monitoring +/x-pack/test/functional/apps/infra @elastic/infra-monitoring-ui +/x-pack/test/api_integration/apis/infra @elastic/infra-monitoring-ui + +# Elastic Stack Monitoring +/x-pack/test/functional/apps/monitoring @elastic/infra-monitoring-ui +/x-pack/test/api_integration/apis/monitoring @elastic/infra-monitoring-ui +/x-pack/test/api_integration/apis/monitoring_collection @elastic/infra-monitoring-ui + +# Fleet +/fleet_packages.json @elastic/fleet +/x-pack/test/fleet_api_integration @elastic/fleet +/x-pack/test/fleet_cypress @elastic/fleet +/x-pack/test/fleet_functional @elastic/fleet +/src/dev/build/tasks/bundle_fleet_packages.ts @elastic/fleet @elastic/kibana-operations + +# APM +/x-pack/test/functional/apps/apm/ @elastic/apm-ui +/x-pack/test/apm_api_integration/ @elastic/apm-ui +/src/apm.js @elastic/kibana-core @vigneshshanmugam +/src/core/types/elasticsearch @elastic/apm-ui +/packages/kbn-utility-types/src/dot.ts @dgieselaar +/packages/kbn-utility-types/src/dot_test.ts @dgieselaar +#CC# /src/plugins/apm_oss/ @elastic/apm-ui +#CC# /x-pack/plugins/observability/ @elastic/apm-ui + +# Uptime +/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/ @elastic/uptime +/x-pack/test/functional/apps/uptime @elastic/uptime +/x-pack/test/functional/es_archives/uptime @elastic/uptime +/x-pack/test/functional/services/uptime @elastic/uptime +/x-pack/test/api_integration/apis/uptime @elastic/uptime +/x-pack/plugins/observability/public/components/shared/exploratory_view @elastic/uptime + + +# Client Side Monitoring / Uptime (lives in APM directories but owned by Uptime) +/x-pack/plugins/apm/public/application/uxApp.tsx @elastic/uptime +/x-pack/plugins/apm/public/components/app/rum_dashboard @elastic/uptime +/x-pack/test/apm_api_integration/tests/csm/ @elastic/uptime + +# Observability onboarding tour +/x-pack/plugins/observability/public/components/shared/tour @elastic/platform-onboarding +/x-pack/test/functional/apps/infra/tour.ts @elastic/platform-onboarding + +### END Observability Plugins + +# Presentation +/test/functional/apps/dashboard/ @elastic/kibana-presentation +/test/functional/apps/dashboard_elements/ @elastic/kibana-presentation +/test/functional/services/dashboard/ @elastic/kibana-presentation +/x-pack/test/functional/apps/canvas/ @elastic/kibana-presentation +/test/plugin_functional/test_suites/panel_actions @elastic/kibana-presentation +#CC# /src/plugins/kibana_react/public/code_editor/ @elastic/kibana-presentation + +# Machine Learning +/x-pack/plugins/ml/common/openapi/ @elastic/mlr-docs +/x-pack/test/accessibility/apps/ml.ts @elastic/ml-ui +/x-pack/test/accessibility/apps/ml_embeddables_in_dashboard.ts @elastic/ml-ui +/x-pack/test/api_integration/apis/ml/ @elastic/ml-ui +/x-pack/test/api_integration_basic/apis/ml/ @elastic/ml-ui +/x-pack/test/functional/apps/ml/ @elastic/ml-ui +/x-pack/test/functional/es_archives/ml/ @elastic/ml-ui +/x-pack/test/functional/services/ml/ @elastic/ml-ui +/x-pack/test/functional_basic/apps/ml/ @elastic/ml-ui +/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/ml/ @elastic/ml-ui +/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/ml_rule_types/ @elastic/ml-ui +/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/ @elastic/ml-ui +/x-pack/test/screenshot_creation/apps/ml_docs @elastic/ml-ui +/x-pack/test/screenshot_creation/services/ml_screenshots.ts @elastic/ml-ui +/docs/api/machine-learning/ @elastic/mlr-docs + +# Additional plugins and packages maintained by the ML team. +/x-pack/test/accessibility/apps/transform.ts @elastic/ml-ui +/x-pack/test/api_integration/apis/transform/ @elastic/ml-ui +/x-pack/test/api_integration_basic/apis/transform/ @elastic/ml-ui +/x-pack/test/functional/apps/transform/ @elastic/ml-ui +/x-pack/test/functional/services/transform/ @elastic/ml-ui +/x-pack/test/functional_basic/apps/transform/ @elastic/ml-ui + +# Maps +#CC# /x-pack/plugins/maps/ @elastic/kibana-gis +/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/plugins/stack_alerts/server/rule_types/geo_containment @elastic/kibana-gis +/x-pack/plugins/stack_alerts/public/rule_types/geo_containment @elastic/kibana-gis +#CC# /x-pack/plugins/file_upload @elastic/kibana-gis + +# Operations +/src/dev/license_checker/config.ts @elastic/kibana-operations +/src/dev/ @elastic/kibana-operations +/src/setup_node_env/ @elastic/kibana-operations +/src/cli/keystore/ @elastic/kibana-operations +/.ci/es-snapshots/ @elastic/kibana-operations +/.github/workflows/ @elastic/kibana-operations +/vars/ @elastic/kibana-operations +/.bazelignore @elastic/kibana-operations +/.bazeliskversion @elastic/kibana-operations +/.bazelrc @elastic/kibana-operations +/.bazelrc.common @elastic/kibana-operations +/.bazelversion @elastic/kibana-operations +/WORKSPACE.bazel @elastic/kibana-operations +/.buildkite/ @elastic/kibana-operations +/kbn_pm/ @elastic/kibana-operations + +# Quality Assurance +/src/dev/code_coverage @elastic/kibana-qa +/vars/*Coverage.groovy @elastic/kibana-qa +/test/functional/services/common @elastic/kibana-qa +/test/functional/services/lib @elastic/kibana-qa +/test/functional/services/remote @elastic/kibana-qa +/test/visual_regression @elastic/kibana-qa +/x-pack/test/visual_regression @elastic/kibana-qa + +# Core +/config/kibana.yml @elastic/kibana-core +/typings/ @elastic/kibana-core +/x-pack/test/saved_objects_field_count/ @elastic/kibana-core +/test/analytics @elastic/kibana-core +#CC# /src/core/server/csp/ @elastic/kibana-core +#CC# /src/plugins/saved_objects/ @elastic/kibana-core +#CC# /x-pack/plugins/cloud/ @elastic/kibana-core +#CC# /x-pack/plugins/features/ @elastic/kibana-core +#CC# /x-pack/plugins/global_search/ @elastic/kibana-core +#CC# /src/plugins/newsfeed @elastic/kibana-core +#CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core + +# Kibana Telemetry +/.telemetryrc.json @elastic/kibana-core +/x-pack/.telemetryrc.json @elastic/kibana-core +/src/plugins/telemetry/schema/ @elastic/kibana-core @elastic/kibana-telemetry +/x-pack/plugins/telemetry_collection_xpack/schema/ @elastic/kibana-core @elastic/kibana-telemetry + +# Kibana Localization +/src/dev/i18n/ @elastic/kibana-localization @elastic/kibana-core +/src/core/public/i18n/ @elastic/kibana-localization @elastic/kibana-core +#CC# /x-pack/plugins/translations/ @elastic/kibana-localization @elastic/kibana-core + +# Kibana Platform Security +/src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security +/test/interactive_setup_api_integration/ @elastic/kibana-security +/test/interactive_setup_functional/ @elastic/kibana-security +/test/plugin_functional/test_suites/core_plugins/rendering.ts @elastic/kibana-security +/x-pack/test/api_integration/apis/security/ @elastic/kibana-security +/x-pack/test/api_integration/apis/spaces/ @elastic/kibana-security +/x-pack/test/ui_capabilities/ @elastic/kibana-security +/x-pack/test/encrypted_saved_objects_api_integration/ @elastic/kibana-security +/x-pack/test/functional/apps/security/ @elastic/kibana-security +/x-pack/test/functional/apps/spaces/ @elastic/kibana-security +/x-pack/test/security_api_integration/ @elastic/kibana-security +/x-pack/test/security_functional/ @elastic/kibana-security +/x-pack/test/spaces_api_integration/ @elastic/kibana-security +/x-pack/test/saved_object_api_integration/ @elastic/kibana-security +#CC# /x-pack/plugins/security/ @elastic/kibana-security + +# Response Ops team +/x-pack/test/alerting_api_integration/ @elastic/response-ops +/x-pack/test/plugin_api_integration/test_suites/task_manager/ @elastic/response-ops +/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/response-ops +/docs/user/alerting/ @elastic/response-ops +/docs/management/connectors/ @elastic/response-ops +/x-pack/test/cases_api_integration/ @elastic/response-ops +/x-pack/test/functional/services/cases/ @elastic/response-ops +/x-pack/test/functional_with_es_ssl/apps/cases/ @elastic/response-ops +/x-pack/test/api_integration/apis/cases/ @elastic/response-ops +/docs/api/actions-and-connectors @elastic/mlr-docs +/docs/api/alerting @elastic/mlr-docs +/docs/api/cases @elastic/mlr-docs +/x-pack/plugins/cases/docs/openapi @elastic/mlr-docs + +# Enterprise Search +/x-pack/test/functional_enterprise_search/ @elastic/enterprise-search-frontend +/x-pack/plugins/enterprise_search/public/applications/shared/doc_links @elastic/ent-search-docs-team + +# Management Experience - Deployment Management +#CC# /x-pack/plugins/cross_cluster_replication/ @elastic/platform-deployment-management + +# Security Solution +/x-pack/test/endpoint_api_integration_no_ingest/ @elastic/security-solution +/x-pack/test/security_solution_endpoint/ @elastic/security-solution +/x-pack/test/functional/es_archives/endpoint/ @elastic/security-solution +/x-pack/test/plugin_functional/test_suites/resolver/ @elastic/security-solution +/x-pack/test/detection_engine_api_integration @elastic/security-solution +/x-pack/test/lists_api_integration @elastic/security-solution +/x-pack/test/api_integration/apis/security_solution @elastic/security-solution +#CC# /x-pack/plugins/security_solution/ @elastic/security-solution + +# Security Solution sub teams + +## Security Solution sub teams - Threat Hunting Investigations + +/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/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 +/x-pack/plugins/security_solution/public/common/components/event_details @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/common/components/events_viewer @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/common/components/markdown_editor @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/detections/components/alerts_kpis @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/detections/components/alerts_table @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/detections/components/alerts_info @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/resolver @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/public/timelines @elastic/security-threat-hunting-investigations + +/x-pack/plugins/security_solution/server/lib/timeline @elastic/security-threat-hunting-investigations + +## Security Solution sub teams - Threat Hunting Explore +/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/common/search_strategy/security_solution/matrix_histogram @elastic/security-threat-hunting-explore +/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/e2e/cases @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/filters @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_e2e/threat_hunting/cases @elastic/security-threat-hunting-explore + +/x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour @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 +/x-pack/plugins/security_solution/public/common/components/header_section @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/inspect @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/last_event_time @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/links @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/matrix_histogram @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/navigation @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/news_feed @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/overview_description_list @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/page @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/sidebar_header @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/tables @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/top_n @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/components/with_hover_actions @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/containers/matrix_histogram @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/common/lib/cell_actions @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/cases @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/explore @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/overview @elastic/security-threat-hunting-explore + +/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/matrix_histogram @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users @elastic/security-threat-hunting-explore + +## Security Solution sub teams - Detections and Response Alerts +/x-pack/plugins/security_solution/common/detection_engine/schemas/alerts @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/common/field_maps @elastic/security-detections-response-alerts + +/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/public/detections/pages/alerts @elastic/security-detections-response-alerts + +/x-pack/plugins/security_solution/server/lib/detection_engine/migrations @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_preview @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/server/lib/detection_engine/signals @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals @elastic/security-detections-response-alerts + +## Security Solution sub teams - Detections and Response Rules +/x-pack/plugins/security_solution/common/detection_engine/fleet_integrations @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/common/detection_engine/prebuilt_rules @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/common/detection_engine/rule_management @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/common/detection_engine/rule_monitoring @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/common/detection_engine/rule_schema @elastic/security-detections-response-rules @elastic/security-detections-response-alerts + +/x-pack/plugins/security_solution/public/common/components/health_truncate_text @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/common/components/links_to_docs @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/common/components/ml_popover @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/common/components/popover_items @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detection_engine/fleet_integrations @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detection_engine/rule_management @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detection_engine/rule_monitoring @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detections/components/callouts @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detections/components/modals/ml_job_upgrade_modal @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/rules/rule_preview @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detections/mitre @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/public/rules @elastic/security-detections-response-rules + +/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_monitoring @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema @elastic/security-detections-response-rules @elastic/security-detections-response-alerts + +/x-pack/plugins/security_solution/server/utils @elastic/security-detections-response-rules + +## Security Solution sub teams - Security 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/common/detection_engine/rule_exceptions @elastic/security-solution-platform + +/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions @elastic/security-solution-platform +/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions_ui @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 +/x-pack/plugins/security_solution/public/detections/containers/detection_engine/lists @elastic/security-solution-platform +/x-pack/plugins/security_solution/public/common/components/sourcerer @elastic/security-solution-platform + +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy @elastic/security-solution-platform +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_exceptions @elastic/security-solution-platform +/x-pack/plugins/security_solution/server/lib/sourcerer @elastic/security-solution-platform + +## Security Threat Intelligence - Under Security Platform +/x-pack/plugins/security_solution/public/common/components/threat_match @elastic/security-solution-platform + +## Security Solution cross teams ownership +/x-pack/plugins/security_solution/cypress/fixtures @elastic/security-detections-response @elastic/security-threat-hunting +/x-pack/plugins/security_solution/cypress/helpers @elastic/security-detections-response @elastic/security-threat-hunting +/x-pack/plugins/security_solution/cypress/e2e/detection_rules @elastic/security-detections-response-rules @elastic/security-detections-response-alerts +/x-pack/plugins/security_solution/cypress/objects @elastic/security-detections-response @elastic/security-threat-hunting +/x-pack/plugins/security_solution/cypress/plugins @elastic/security-detections-response @elastic/security-threat-hunting +/x-pack/plugins/security_solution/cypress/screens/common @elastic/security-detections-response @elastic/security-threat-hunting +/x-pack/plugins/security_solution/cypress/support @elastic/security-detections-response @elastic/security-threat-hunting +/x-pack/plugins/security_solution/cypress/urls @elastic/security-threat-hunting-investigations @elastic/security-solution-platform + +/x-pack/plugins/security_solution/common/ecs @elastic/security-threat-hunting-investigations +/x-pack/plugins/security_solution/common/test @elastic/security-detections-response-rules @elastic/security-detections-response-alerts + +/x-pack/plugins/security_solution/public/common/components/callouts @elastic/security-detections-response +/x-pack/plugins/security_solution/public/common/components/hover_actions @elastic/security-threat-hunting-explore @elastic/security-threat-hunting-investigations + +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions @elastic/security-solution-platform @elastic/security-detections-response-rules +/x-pack/plugins/security_solution/server/routes @elastic/security-detections-response @elastic/security-threat-hunting + +## Security Solution sub teams - security-defend-workflows +/x-pack/plugins/security_solution/public/management/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/common/lib/endpoint*/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/common/components/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/common/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/lists_integration/endpoint/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/lib/license/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/fleet_integration/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/scripts/endpoint/event_filters/ @elastic/security-defend-workflows +/x-pack/plugins/security_solution/scripts/endpoint/trusted_apps/ @elastic/security-defend-workflows +/x-pack/test/security_solution_endpoint/apps/endpoint/ @elastic/security-defend-workflows +/x-pack/test/security_solution_endpoint_api_int/ @elastic/security-defend-workflows + +## Security Solution sub teams - security-telemetry (Data Engineering) +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_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 + +## Security Solution sub teams - adaptive-workload-protection +x-pack/plugins/security_solution/public/common/components/sessions_viewer @elastic/awp-viz +x-pack/plugins/security_solution/public/kubernetes @elastic/awp-viz + +## Security Solution sub teams - Protections Experience +x-pack/plugins/security_solution/public/threat_intelligence @elastic/protections-experience +x-pack/test/threat_intelligence_cypress @elastic/protections-experience + +# Security Defend Workflows - OSQuery Ownership +/x-pack/plugins/security_solution/common/detection_engine/rule_response_actions @elastic/security-defend-workflows +/x-pack/plugins/security_solution/public/detection_engine/rule_response_actions @elastic/security-defend-workflows +/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions @elastic/security-defend-workflows + +# Cloud Security Posture +/x-pack/plugins/security_solution/public/cloud_security_posture @elastic/kibana-cloud-security-posture +/x-pack/test/api_integration/apis/cloud_security_posture/ @elastic/kibana-cloud-security-posture +/x-pack/test/cloud_security_posture_functional/ @elastic/kibana-cloud-security-posture + + +# Security Solution onboarding tour +/x-pack/plugins/security_solution/public/common/components/guided_onboarding @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/cypress/e2e/guided_onboarding @elastic/security-threat-hunting-explore # Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design +# Observability design +/x-pack/plugins/apm/**/*.scss @elastic/observability-design +/x-pack/plugins/infra/**/*.scss @elastic/observability-design +/x-pack/plugins/fleet/**/*.scss @elastic/observability-design +/x-pack/plugins/observability/**/*.scss @elastic/observability-design +/x-pack/plugins/monitoring/**/*.scss @elastic/observability-design + +# Ent. Search design +/x-pack/plugins/enterprise_search/**/*.scss @elastic/ent-search-design + +# Security design +/x-pack/plugins/endpoint/**/*.scss @elastic/security-design +/x-pack/plugins/security_solution/**/*.scss @elastic/security-design + +# Logstash +#CC# /x-pack/plugins/logstash/ @elastic/logstash + +# EUI design +/src/plugins/kibana_react/public/page_template/ @elastic/eui-design @elastic/appex-sharedux + +# Landing page for guided onboarding in Home plugin +/src/plugins/home/public/application/components/guided_onboarding @elastic/platform-onboarding + # Changes to translation files should not ping code reviewers x-pack/plugins/translations/translations + +#### +## These rules are always last so they take ultimate priority over everything else +#### + + +# Design (at the bottom for specificity of SASS files) +**/*.scss @elastic/kibana-design + +#### +## These rules are always last so they take ultimate priority over everything else +#### + +**/*.scss @elastic/kibana-design diff --git a/packages/kbn-generate/src/commands/codeowners_command.ts b/packages/kbn-generate/src/commands/codeowners_command.ts index ed3f51d5bc087..157624081d689 100644 --- a/packages/kbn-generate/src/commands/codeowners_command.ts +++ b/packages/kbn-generate/src/commands/codeowners_command.ts @@ -16,77 +16,63 @@ import type { GenerateCommand } from '../generate_command'; const REL = '.github/CODEOWNERS'; -const GENERATED_START = ` +const GENERATED_START = `#### +## Everything at the top of the codeowners file is auto generated based on the +## "owner" fields in the kibana.jsonc files at the root of each package. This +## file is automatically updated by CI or can be updated locally by running +## \`node scripts/generate codeowners\`. +#### + +`; +const GENERATED_END = ` #### -## Everything below this comment is automatically generated based on kibana.jsonc -## "owner" fields. This file is automatically updated by CI or can be updated locally -## by running \`node scripts/generate codeowners\`. +## Everything below this line overrides the default assignments for each package. +## Items lower in the file have higher precedence: +## https://help.github.com/articles/about-codeowners/ #### - `; -const GENERATED_TRAILER = ` +const ULTIMATE_PRIORITY_RULES = ` +#### +## These rules are always last so they take ultimate priority over everything else +#### -# Design (at the bottom for specificity of SASS files) **/*.scss @elastic/kibana-design - -# Changes to translation files should not ping code reviewers -x-pack/plugins/translations/translations `; -function normalizeDir(dirish: string): string { - const trim = dirish.trim(); - if (trim.startsWith('/')) { - return normalizeDir(trim.slice(1)); - } - - if (trim.endsWith('/')) { - return normalizeDir(trim.slice(0, -1)); - } - - return trim; -} - export const CodeownersCommand: GenerateCommand = { name: 'codeowners', description: 'Update the codeowners file based on the package manifest files', usage: 'node scripts/generate codeowners', async run({ log }) { const pkgs = getPackages(REPO_ROOT); - const coPath = Path.resolve(REPO_ROOT, REL); - const codeowners = await Fsp.readFile(coPath, 'utf8'); - let genStart: number | undefined = codeowners.indexOf(GENERATED_START); - if (genStart === -1) { - genStart = undefined; - log.warning(`${REL} doesn't include the expected start-marker for injecting generated text`); + const path = Path.resolve(REPO_ROOT, REL); + const oldCodeowners = await Fsp.readFile(path, 'utf8'); + let content = oldCodeowners; + + // strip the old generated output + const genEnd = content.indexOf(GENERATED_END); + if (genEnd !== -1) { + content = content.slice(genEnd + GENERATED_END.length); } - const pkgDirs = new Set(pkgs.map((pkg) => pkg.normalizedRepoRelativeDir)); - const lines = []; - - for (const line of codeowners.slice(0, genStart).split('\n')) { - if (line.startsWith('#') || !line.trim()) { - lines.push(line); - continue; - } - - const dir = normalizeDir(line.split('@')[0]); - if (!pkgDirs.has(dir)) { - lines.push(line); - } + // strip the old ultimate rules + const ultStart = content.indexOf(ULTIMATE_PRIORITY_RULES); + if (ultStart !== -1) { + content = content.slice(0, ultStart); } - const newCodeowners = `${lines.join('\n')}${GENERATED_START}${pkgs + const newCodeowners = `${GENERATED_START}${pkgs .map((pkg) => `${pkg.normalizedRepoRelativeDir} ${pkg.manifest.owner.join(' ')}`) - .join('\n')}${GENERATED_TRAILER}`; + .join('\n')}${GENERATED_END}${content}${ULTIMATE_PRIORITY_RULES}`; - if (codeowners === newCodeowners) { + if (newCodeowners === oldCodeowners) { log.success(`${REL} is already up-to-date`); return; } - await Fsp.writeFile(coPath, newCodeowners); + await Fsp.writeFile(path, newCodeowners); log.info(`${REL} updated`); }, }; From a1c55c6f137603fb0df798351c08be7f50d950bc Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 9 Feb 2023 21:57:10 -0700 Subject: [PATCH 063/203] [ci] build next docs in PRs when relevant files change (#149991) After chatting with @KOTungseth, @scottybollinger, and @glitteringkatie we've decided to add a CI step to the Kibana repo that will run when changes to next-doc related code is made. This step will checkout the repository containing configuration for the docs.elastic.dev website (which is currently private, sorry) and then ensure that the build can be completed with a local copy of all the repositories. It does this by reading the `config/content.js` files and cloning all of the repositories listed, then rewriting the content.js file with a map telling the build system to read files from the local repos (which are pre-cached by the packer cache job) and the local Kibana repo (which represents the changes in the PR). This script also runs locally by running `node scripts/validate_next_docs`. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../pull_request/check_next_docs.yml | 10 ++ .buildkite/scripts/common/env.sh | 2 + .buildkite/scripts/packer_cache.sh | 12 ++ .../pipelines/pull_request/pipeline.ts | 13 ++ .../next_docs/build_and_validate_docs.sh | 13 ++ .eslintrc.js | 1 + .github/CODEOWNERS | 1 + package.json | 1 + packages/kbn-validate-next-docs-cli/README.md | 5 + packages/kbn-validate-next-docs-cli/config.ts | 64 +++++++ packages/kbn-validate-next-docs-cli/error.ts | 19 ++ .../kbn-validate-next-docs-cli/jest.config.js | 13 ++ .../kbn-validate-next-docs-cli/kibana.jsonc | 6 + .../kbn-validate-next-docs-cli/package.json | 7 + packages/kbn-validate-next-docs-cli/repos.ts | 170 ++++++++++++++++++ .../kbn-validate-next-docs-cli/tsconfig.json | 22 +++ .../validate_next_docs_cli.ts | 84 +++++++++ scripts/validate_next_docs.js | 10 ++ tsconfig.base.json | 2 + yarn.lock | 4 + 20 files changed, 459 insertions(+) create mode 100644 .buildkite/pipelines/pull_request/check_next_docs.yml create mode 100755 .buildkite/scripts/steps/next_docs/build_and_validate_docs.sh create mode 100644 packages/kbn-validate-next-docs-cli/README.md create mode 100644 packages/kbn-validate-next-docs-cli/config.ts create mode 100644 packages/kbn-validate-next-docs-cli/error.ts create mode 100644 packages/kbn-validate-next-docs-cli/jest.config.js create mode 100644 packages/kbn-validate-next-docs-cli/kibana.jsonc create mode 100644 packages/kbn-validate-next-docs-cli/package.json create mode 100644 packages/kbn-validate-next-docs-cli/repos.ts create mode 100644 packages/kbn-validate-next-docs-cli/tsconfig.json create mode 100644 packages/kbn-validate-next-docs-cli/validate_next_docs_cli.ts create mode 100644 scripts/validate_next_docs.js diff --git a/.buildkite/pipelines/pull_request/check_next_docs.yml b/.buildkite/pipelines/pull_request/check_next_docs.yml new file mode 100644 index 0000000000000..16b9145661a32 --- /dev/null +++ b/.buildkite/pipelines/pull_request/check_next_docs.yml @@ -0,0 +1,10 @@ +steps: + - command: .buildkite/scripts/steps/next_docs/build_and_validate_docs.sh + label: 'Build and Validate Next Docs' + agents: + queue: n2-4-spot + timeout_in_minutes: 30 + retry: + automatic: + - exit_status: '-1' + limit: 3 diff --git a/.buildkite/scripts/common/env.sh b/.buildkite/scripts/common/env.sh index c357b5421a903..ccaeb7b0dc5d9 100755 --- a/.buildkite/scripts/common/env.sh +++ b/.buildkite/scripts/common/env.sh @@ -12,6 +12,8 @@ PARENT_DIR="$(cd "$KIBANA_DIR/.."; pwd)" export PARENT_DIR export WORKSPACE="${WORKSPACE:-$PARENT_DIR}" +export DOCS_REPO_CACHE_DIR="$HOME/.docs-repos" + # A few things, such as Chrome, respect this variable # For many agent types, the workspace is mounted on a local ssd, so will be faster than the default tmp dir location if [[ -d /opt/local-ssd/buildkite ]]; then diff --git a/.buildkite/scripts/packer_cache.sh b/.buildkite/scripts/packer_cache.sh index 673396af77e57..16d46f7546179 100755 --- a/.buildkite/scripts/packer_cache.sh +++ b/.buildkite/scripts/packer_cache.sh @@ -13,3 +13,15 @@ yarn kbn bootstrap for version in $(cat versions.json | jq -r '.versions[].version'); do node scripts/es snapshot --download-only --base-path "$ES_CACHE_DIR" --version "$version" done + +echo "--- Logging into vault to access private repos" +VAULT_ROLE_ID="$(retry 5 15 gcloud secrets versions access latest --secret=kibana-buildkite-vault-role-id)" +VAULT_SECRET_ID="$(retry 5 15 gcloud secrets versions access latest --secret=kibana-buildkite-vault-secret-id)" +VAULT_TOKEN=$(retry 5 30 vault write -field=token auth/approle/login role_id="$VAULT_ROLE_ID" secret_id="$VAULT_SECRET_ID") +retry 5 30 vault login -no-print "$VAULT_TOKEN" + +GITHUB_TOKEN="$(retry 5 5 vault read -field=github_token secret/kibana-issues/dev/kibanamachine)" +export GITHUB_TOKEN + +echo "--- Cloning repos for docs build" +node scripts/validate_next_docs --clone-only diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index b9ac7a2435404..5fb29fc87c228 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -171,6 +171,19 @@ const uploadPipeline = (pipelineContent: string | object) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/webpack_bundle_analyzer.yml')); } + if ( + (await doAnyChangesMatch([ + /\.docnav\.json$/, + /\.apidocs\.json$/, + /\.devdocs\.json$/, + /\.mdx$/, + /^dev_docs\/.*(png|gif|jpg|jpeg|webp)$/, + ])) || + GITHUB_PR_LABELS.includes('ci:build-next-docs') + ) { + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/check_next_docs.yml')); + } + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/post_build.yml')); uploadPipeline(pipeline.join('\n')); diff --git a/.buildkite/scripts/steps/next_docs/build_and_validate_docs.sh b/.buildkite/scripts/steps/next_docs/build_and_validate_docs.sh new file mode 100755 index 0000000000000..28f7bba3c46a1 --- /dev/null +++ b/.buildkite/scripts/steps/next_docs/build_and_validate_docs.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/bootstrap.sh + +echo "--- Build docs" + +echo "⚠️ run 'node scripts/validate_next_docs --debug' locally to debug ⚠️" +node scripts/validate_next_docs + + + diff --git a/.eslintrc.js b/.eslintrc.js index 3474d3c588707..c0b1d8d34e46d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1736,6 +1736,7 @@ module.exports = { { files: [ 'packages/kbn-{package-*,repo-*,dep-*}/**/*', + 'packages/kbn-validate-next-docs-cli/**/*', 'packages/kbn-find-used-node-modules/**/*', ], rules: { diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6017050be748a..e91dff193338d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -669,6 +669,7 @@ packages/kbn-utility-types @elastic/kibana-core packages/kbn-utility-types-jest @elastic/kibana-operations packages/kbn-utils @elastic/kibana-operations x-pack/plugins/ux @elastic/uptime +packages/kbn-validate-next-docs-cli @elastic/kibana-operations src/plugins/vis_default_editor @elastic/kibana-visualizations src/plugins/vis_types/gauge @elastic/kibana-visualizations src/plugins/vis_types/heatmap @elastic/kibana-visualizations diff --git a/package.json b/package.json index 0aaf633a71dfb..c787bb1942060 100644 --- a/package.json +++ b/package.json @@ -1104,6 +1104,7 @@ "@kbn/tooling-log": "link:packages/kbn-tooling-log", "@kbn/ts-projects": "link:packages/kbn-ts-projects", "@kbn/ts-type-check-cli": "link:packages/kbn-ts-type-check-cli", + "@kbn/validate-next-docs-cli": "link:packages/kbn-validate-next-docs-cli", "@kbn/web-worker-stub": "link:packages/kbn-web-worker-stub", "@kbn/whereis-pkg-cli": "link:packages/kbn-whereis-pkg-cli", "@kbn/yarn-lock-validator": "link:packages/kbn-yarn-lock-validator", diff --git a/packages/kbn-validate-next-docs-cli/README.md b/packages/kbn-validate-next-docs-cli/README.md new file mode 100644 index 0000000000000..53a61d2fb05ff --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/README.md @@ -0,0 +1,5 @@ +# @kbn/validate-next-docs-cli + +Clone a bunch of repos needed to build the next-docs with the latest version of the changes in the repo. This is only used for validating changes in CI with full validation of all IDs. This isn't intended for local development (except for debugging). + +To build the docs locally run: `./scripts/dev_docs.sh` \ No newline at end of file diff --git a/packages/kbn-validate-next-docs-cli/config.ts b/packages/kbn-validate-next-docs-cli/config.ts new file mode 100644 index 0000000000000..541ee061cc302 --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/config.ts @@ -0,0 +1,64 @@ +/* + * Copyright 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 Fs from 'fs'; + +import { Repo } from './repos'; + +export interface Source { + type: string; + location: string; + subdirs?: string[]; +} + +export class Config { + path: string; + backupPath: string; + + constructor(private readonly repo: Repo) { + this.path = this.repo.resolve('config/content.js'); + this.backupPath = `${this.path}.backup`; + this.restore(); + } + + private read(): { content: { sources: Source[]; nav: unknown } } { + delete require.cache[this.path]; + return require(this.path); + } + + private restore() { + if (Fs.existsSync(this.backupPath)) { + Fs.renameSync(this.backupPath, this.path); + } + } + + getSources() { + return this.read().content.sources; + } + + setSources(sources: Source[]) { + this.restore(); + Fs.copyFileSync(this.path, this.backupPath); + + const current = this.read(); + + Fs.writeFileSync( + this.path, + `module.exports = ${JSON.stringify( + { + content: { + ...current.content, + sources, + }, + }, + null, + 2 + )}` + ); + } +} diff --git a/packages/kbn-validate-next-docs-cli/error.ts b/packages/kbn-validate-next-docs-cli/error.ts new file mode 100644 index 0000000000000..a42af96f85f47 --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/error.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 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 { createFailError } from '@kbn/dev-cli-errors'; + +export function quietFail(msg: string): never { + throw createFailError( + `${msg}${ + process.env.CI + ? ` (in order to avoid potential info leaks, we've hidden the logging output. Please run this command locally with --debug to get logging output)` + : '' + }` + ); +} diff --git a/packages/kbn-validate-next-docs-cli/jest.config.js b/packages/kbn-validate-next-docs-cli/jest.config.js new file mode 100644 index 0000000000000..f9b23ca4f8d52 --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/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/jest_node', + rootDir: '../..', + roots: ['/packages/kbn-validate-next-docs-cli'], +}; diff --git a/packages/kbn-validate-next-docs-cli/kibana.jsonc b/packages/kbn-validate-next-docs-cli/kibana.jsonc new file mode 100644 index 0000000000000..5a6ffafe185bf --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/kibana.jsonc @@ -0,0 +1,6 @@ +{ + "type": "shared-common", + "id": "@kbn/validate-next-docs-cli", + "owner": "@elastic/kibana-operations", + "devOnly": true +} diff --git a/packages/kbn-validate-next-docs-cli/package.json b/packages/kbn-validate-next-docs-cli/package.json new file mode 100644 index 0000000000000..ec6f7743d00ac --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/validate-next-docs-cli", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0", + "main": "./validate_next_docs_cli" +} \ No newline at end of file diff --git a/packages/kbn-validate-next-docs-cli/repos.ts b/packages/kbn-validate-next-docs-cli/repos.ts new file mode 100644 index 0000000000000..8a408d506bb42 --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/repos.ts @@ -0,0 +1,170 @@ +/* + * Copyright 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 Fs from 'fs'; +import Os from 'os'; +import Path from 'path'; +import Rl from 'readline'; + +import Chalk from 'chalk'; +import execa from 'execa'; +import { ToolingLog } from '@kbn/tooling-log'; + +import { quietFail } from './error'; + +function lines(read: NodeJS.ReadableStream) { + return Rl.createInterface({ + input: read, + crlfDelay: Infinity, + }); +} + +function getGithubBase() { + try { + const originUrl = execa.sync('git', ['remote', 'get-url', 'origin'], { + encoding: 'utf8', + }).stdout; + + if (originUrl.startsWith('git@')) { + return `git@github.com:`; + } + } catch { + // noop + } + + if (process.env.GITHUB_TOKEN) { + return `https://${process.env.GITHUB_TOKEN}@github.com/`; + } + + return `https://github.com/`; +} + +export class Repo { + constructor( + private readonly log: ToolingLog, + private readonly name: string, + private readonly dir: string, + private readonly githubBase: string + ) {} + + resolve(...segs: string[]) { + return Path.resolve(this.dir, ...segs); + } + + exists() { + if (!Fs.existsSync(this.dir)) { + return false; + } + + if (!Fs.statSync(this.dir).isDirectory()) { + throw new Error(`[${this.name}] directory exists but it's not a directory like it should be`); + } + + return true; + } + + async run(cmd: string, args: string[], opts: { desc: string; showOutput?: boolean }) { + try { + if (!opts.showOutput) { + await execa(cmd, args, { + cwd: this.dir, + maxBuffer: Infinity, + }); + return; + } + + await this.log.indent(4, async () => { + const proc = execa(cmd, args, { + cwd: this.dir, + stdio: ['ignore', 'pipe', 'pipe'], + }); + + await Promise.all([ + (async () => { + for await (const line of lines(proc.stdout!)) { + this.log.write(Chalk.dim('out '), line); + } + })(), + (async () => { + for await (const line of lines(proc.stderr!)) { + this.log.write(Chalk.red('err '), line); + } + })(), + new Promise((resolve, reject) => { + proc.once('exit', resolve).once('exit', reject); + }), + ]); + }); + } catch (error) { + this.log.debug( + `Failed to run [${opts.desc}] in [${this.name}]`, + opts.showOutput ? error : undefined + ); + + throw quietFail(`${this.name}: ${opts.desc} failed`); + } + } + + async update() { + try { + this.log.info('updating', this.name); + await this.run('git', ['reset', '--hard'], { desc: 'git reset --hard' }); + await this.run( + 'git', + [ + 'clean', + '-fdx', + ...(this.name === 'elastic/docs.elastic.dev' + ? ['-e', '/.docsmobile', '-e', '/node_modules'] + : []), + ], + { desc: 'git clean -fdx' } + ); + await this.run('git', ['pull'], { desc: 'git pull' }); + } catch { + quietFail(`failed to update ${this.name}`); + } + } + + async clone() { + try { + this.log.info('cloning', this.name); + Fs.mkdirSync(this.dir, { recursive: true }); + const depth = process.env.CI ? ['--depth', '1'] : []; + await this.run('git', ['clone', ...depth, `${this.githubBase}${this.name}.git`, '.'], { + desc: 'git clone ...', + }); + } catch { + quietFail(`Failed to clone ${this.name}`); + } + } +} + +export class Repos { + githubBase = getGithubBase(); + repoDir = Path.resolve(Os.userInfo().homedir, '.cache/next-docs/repos'); + + constructor(private readonly log: ToolingLog) {} + + async init(repoName: string) { + const repo = new Repo( + this.log, + repoName, + Path.resolve(this.repoDir, repoName), + this.githubBase + ); + + if (repo.exists()) { + await repo.update(); + } else { + await repo.clone(); + } + + return repo; + } +} diff --git a/packages/kbn-validate-next-docs-cli/tsconfig.json b/packages/kbn-validate-next-docs-cli/tsconfig.json new file mode 100644 index 0000000000000..4c04ba2180927 --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/dev-cli-errors", + "@kbn/tooling-log", + "@kbn/dev-cli-runner", + "@kbn/repo-info", + ] +} diff --git a/packages/kbn-validate-next-docs-cli/validate_next_docs_cli.ts b/packages/kbn-validate-next-docs-cli/validate_next_docs_cli.ts new file mode 100644 index 0000000000000..9cfca8d442fd6 --- /dev/null +++ b/packages/kbn-validate-next-docs-cli/validate_next_docs_cli.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 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 { run } from '@kbn/dev-cli-runner'; +import { createFailError } from '@kbn/dev-cli-errors'; +import { REPO_ROOT } from '@kbn/repo-info'; + +import { Repos } from './repos'; +import { Config, Source } from './config'; +import { quietFail } from './error'; + +run( + async ({ log, flagsReader }) => { + const cloneOnly = flagsReader.boolean('clone-only'); + + const repos = new Repos(log); + const docsRepo = await repos.init('elastic/docs.elastic.dev'); + const contentConfig = new Config(docsRepo); + const sources = contentConfig.getSources().filter((s) => s.location !== 'elastic/kibana'); + + if (sources.some((s) => s.type !== 'github')) { + throw createFailError( + 'expected all content.js sources from docs.elastic.dev to have "type: github"' + ); + } + + const localCloneSources = await Promise.all( + sources.map(async (source): Promise => { + const repo = await repos.init(source.location); + + return { + type: 'file', + location: repo.resolve(), + }; + }) + ); + + if (cloneOnly) { + log.success('cloned repos'); + return; + } + + log.info('[docs.elastic.dev] updated sources to point to local repos'); + contentConfig.setSources([ + ...localCloneSources, + { + type: 'file', + location: REPO_ROOT, + }, + ]); + + const showOutput = flagsReader.boolean('debug') || flagsReader.boolean('verbose'); + try { + log.info('[docs.elastic.dev] installing deps with yarn'); + await docsRepo.run('yarn', [], { desc: 'yarn install', showOutput }); + + log.info('[docs.elastic.dev] initializing docsmobile'); + await docsRepo.run('yarn', ['docsmobile', 'init'], { + desc: 'yarn docsmobile init', + showOutput, + }); + + log.info('[docs.elastic.dev] building'); + await docsRepo.run('yarn', ['build'], { desc: 'yarn build', showOutput }); + } catch { + quietFail(`failed to build docs`); + } + + log.success('docs built successfully'); + }, + { + flags: { + boolean: ['clone-only'], + help: ` + --clone-only Simply clone the repos, used to populate the worker images + `, + }, + } +); diff --git a/scripts/validate_next_docs.js b/scripts/validate_next_docs.js new file mode 100644 index 0000000000000..b53e62842e70f --- /dev/null +++ b/scripts/validate_next_docs.js @@ -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. + */ + +require('../src/setup_node_env'); +require('@kbn/validate-next-docs-cli'); diff --git a/tsconfig.base.json b/tsconfig.base.json index 6b4a26c43479a..6d869c8697b7a 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1332,6 +1332,8 @@ "@kbn/utils/*": ["packages/kbn-utils/*"], "@kbn/ux-plugin": ["x-pack/plugins/ux"], "@kbn/ux-plugin/*": ["x-pack/plugins/ux/*"], + "@kbn/validate-next-docs-cli": ["packages/kbn-validate-next-docs-cli"], + "@kbn/validate-next-docs-cli/*": ["packages/kbn-validate-next-docs-cli/*"], "@kbn/vis-default-editor-plugin": ["src/plugins/vis_default_editor"], "@kbn/vis-default-editor-plugin/*": ["src/plugins/vis_default_editor/*"], "@kbn/vis-type-gauge-plugin": ["src/plugins/vis_types/gauge"], diff --git a/yarn.lock b/yarn.lock index c5a662bdf9bd2..c89100758294f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5389,6 +5389,10 @@ version "0.0.0" uid "" +"@kbn/validate-next-docs-cli@link:packages/kbn-validate-next-docs-cli": + version "0.0.0" + uid "" + "@kbn/vis-default-editor-plugin@link:src/plugins/vis_default_editor": version "0.0.0" uid "" From be045e29c01474f6179e09b77b4f7c7558087276 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 10 Feb 2023 00:46:18 -0500 Subject: [PATCH 064/203] [api-docs] 2023-02-10 Daily api_docs build (#150831) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/244 --- 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_chat.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 4 +- api_docs/controls.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/ecs_data_quality_dashboard.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/files_management.mdx | 2 +- api_docs/fleet.devdocs.json | 4 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.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_alerts_ui_shared.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_analytics_shippers_gainsight.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.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_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mocks.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 +- .../kbn_content_management_content_editor.mdx | 2 +- .../kbn_content_management_table_list.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_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.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_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.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 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_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 +- ...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_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.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_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_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_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.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_test_helpers_kbn_server.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.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_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.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_cypress_config.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.devdocs.json | 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_ecs.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_es.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_es_types.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 +- .../kbn_ftr_common_functional_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.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_i18n_react.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_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.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_date_picker.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_url_state.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_osquery_io_ts_types.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_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.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 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- ...ared_ux_avatar_user_profile_components.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.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 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_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_prompt_not_found.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_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.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_test_subj_selector.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.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.devdocs.json | 100 ++++++++++++++++++ api_docs/kibana_react.mdx | 4 +- 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/notifications.mdx | 2 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 12 +-- api_docs/presentation_util.devdocs.json | 37 +++++++ api_docs/presentation_util.mdx | 4 +- api_docs/profiling.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/stack_connectors.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_histogram.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 +- 480 files changed, 624 insertions(+), 487 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 4a1636c0b6604..249e133aa8825 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: 2023-02-09 +date: 2023-02-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 6861da631f571..2262d8a151a42 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: 2023-02-09 +date: 2023-02-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 133b7904c4ea1..fdcb6d8d2d3f7 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: 2023-02-09 +date: 2023-02-10 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 cfba3449e1e98..6af8f05ef5586 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: 2023-02-09 +date: 2023-02-10 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 36a6809a864a4..8ef86d44a6787 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: 2023-02-09 +date: 2023-02-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 5fcae16afd66a..c2aa27ad2a702 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: 2023-02-09 +date: 2023-02-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 9cb0a9d438e5b..434960034fe78 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: 2023-02-09 +date: 2023-02-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 d5b55fc41918b..50021680ee1cc 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: 2023-02-09 +date: 2023-02-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 bcd1b98325f69..10b4504b015e1 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: 2023-02-09 +date: 2023-02-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 592897ece19d6..4db2c3b68146c 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: 2023-02-09 +date: 2023-02-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 bcd015fbbc2a8..2079ffc32ea41 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index e585b0114ad08..9b4c89ef5bcca 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 9c3a4362afddd..ff08dcbc3cc07 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 5d63726e6089f..2b9c53b03f7f1 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 01ecab5ec0f4d..7f88c7651c2e4 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 67f06aaea6d47..fadabf7911f32 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: 2023-02-09 +date: 2023-02-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 9bdbaa509bde9..83f031262b5c1 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 9e890c09c5c89..0ecf9646bbae2 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,14 +8,14 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; Content management app -Contact [@elastic/kibana-global-experience](https://github.com/orgs/elastic/teams/kibana-global-experience) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 33b1de5640f7f..dc5fab865c7be 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 081a63980a0ff..0254cca5e044f 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: 2023-02-09 +date: 2023-02-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 554a73dafc10a..bf520e27b1a94 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: 2023-02-09 +date: 2023-02-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 4374547b33e4e..ea983a770d0dc 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: 2023-02-09 +date: 2023-02-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 e0aa55772af62..47b49d9091520 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: 2023-02-09 +date: 2023-02-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 f028522d5d0fd..7f8201ba0c134 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: 2023-02-09 +date: 2023-02-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 e400eea15e1d1..2c11349be3bb2 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: 2023-02-09 +date: 2023-02-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 9b933af1305ff..50979d69769d1 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: 2023-02-09 +date: 2023-02-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 8ac4ff750b4d4..93624b2651c61 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: 2023-02-09 +date: 2023-02-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 305a9ff2e14f0..9c12164cfa8b7 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: 2023-02-09 +date: 2023-02-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 c27da3bf5df62..d971f5857b1a7 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: 2023-02-09 +date: 2023-02-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 04dff69ad53cd..9b1c9d30a79d5 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: 2023-02-09 +date: 2023-02-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 f7a57e3892425..be0e87daad939 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 5c5b2d44bf2ec..b9e4dfb267687 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 54bb94c8dfa64..ba40f393a522f 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 1db5ed65d0655..532d8db6774fd 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: 2023-02-09 +date: 2023-02-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 5c741d9fd04ae..a7a3661a71fb7 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: 2023-02-09 +date: 2023-02-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 86926e0166907..6e419ec8a6a98 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 37c83323ecf34..96b2db398c91b 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index d88fbce954ab2..876079081830e 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: 2023-02-09 +date: 2023-02-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 e7ea5a558849d..38dd6adc92992 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: 2023-02-09 +date: 2023-02-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 c3e508d8288c7..c551ee2586967 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: 2023-02-09 +date: 2023-02-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 408b766d50d4a..8ec7b05e841f8 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: 2023-02-09 +date: 2023-02-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 1efe83b2148f8..aeb0af610b57a 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: 2023-02-09 +date: 2023-02-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 542295f4e6f4c..b148446e2d881 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: 2023-02-09 +date: 2023-02-10 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 c623776fa5c9a..025ac47f434cb 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: 2023-02-09 +date: 2023-02-10 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 3eb11e9412469..7cb3308252987 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: 2023-02-09 +date: 2023-02-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 ac248077b10e0..c86ac6ce53673 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: 2023-02-09 +date: 2023-02-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 9624b53019718..895805a6b65b1 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: 2023-02-09 +date: 2023-02-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 f6a0347fdf5a7..f21c3c3cac0d0 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: 2023-02-09 +date: 2023-02-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 819908cec963e..d01fe86399c2a 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: 2023-02-09 +date: 2023-02-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 4905340a3ec55..59f564cb58008 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: 2023-02-09 +date: 2023-02-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 c448af489e8d9..02470329817ca 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: 2023-02-09 +date: 2023-02-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 4dba869f70612..2fdbb4f374c9b 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: 2023-02-09 +date: 2023-02-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 2d8e2f92d5b5b..7df33efbd4f4a 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: 2023-02-09 +date: 2023-02-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 81a6b08712ac5..04e7141d1626e 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: 2023-02-09 +date: 2023-02-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 37518c256b7d8..d40831dabf02f 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: 2023-02-09 +date: 2023-02-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 7561c88545250..31abcab4c6336 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: 2023-02-09 +date: 2023-02-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 3446d219d7394..a95001d5455e3 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: 2023-02-09 +date: 2023-02-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 c4d9f53e67edc..31e3bc9ead634 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: 2023-02-09 +date: 2023-02-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 18af6bcfd5efb..f5d2e845a38de 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: 2023-02-09 +date: 2023-02-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 96967ed5837ac..d384c80599e16 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: 2023-02-09 +date: 2023-02-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 1bc3b915f11ee..e8fc842acc623 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: 2023-02-09 +date: 2023-02-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 6865d18002875..10c21f3d137b2 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 5b9603ae9399d..be51167a94490 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index e3730fe873405..1a95d073f190b 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -4544,7 +4544,7 @@ "section": "def-common.SavedObjectsClientContract", "text": "SavedObjectsClientContract" }, - ", options: Readonly<{ page?: number | undefined; kuery?: any; sortField?: string | undefined; perPage?: number | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { withPackagePolicies?: boolean | undefined; }) => Promise<{ items: ", + ", options: Readonly<{ page?: number | undefined; kuery?: any; sortField?: string | undefined; perPage?: number | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { withPackagePolicies?: boolean | undefined; fields?: string[] | undefined; }) => Promise<{ items: ", { "pluginId": "fleet", "scope": "common", @@ -4587,7 +4587,7 @@ "label": "options", "description": [], "signature": [ - "Readonly<{ page?: number | undefined; kuery?: any; sortField?: string | undefined; perPage?: number | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { withPackagePolicies?: boolean | undefined; }" + "Readonly<{ page?: number | undefined; kuery?: any; sortField?: string | undefined; perPage?: number | undefined; sortOrder?: \"asc\" | \"desc\" | undefined; showUpgradeable?: boolean | undefined; } & {}> & { withPackagePolicies?: boolean | undefined; fields?: string[] | undefined; }" ], "path": "x-pack/plugins/fleet/server/services/agent_policy.ts", "deprecated": false, diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index fd5e580b7fdd6..6cc1366733cae 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: 2023-02-09 +date: 2023-02-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 ccc29726ef282..32fa01bd00184 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 8e49dd31bcabc..e456ea36f950e 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index d0ca7b48dc3ee..0d77ffd0c8531 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 377c01d4f92ad..4fdf18d01db0c 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index ed84bf34e3bd6..7cade37db9826 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: 2023-02-09 +date: 2023-02-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 bc06e6bfcfb39..76668abfc8095 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: 2023-02-09 +date: 2023-02-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 2f44bef831edc..ca312e86578d1 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: 2023-02-09 +date: 2023-02-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 9f657fd76e9ed..96332732629b1 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: 2023-02-09 +date: 2023-02-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 3e9ae85bfeefe..eeac4bdb338e0 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: 2023-02-09 +date: 2023-02-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 c5241f57706c1..3d5cc79a92658 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: 2023-02-09 +date: 2023-02-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 160a6f41150ca..07b0c0d456962 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: 2023-02-09 +date: 2023-02-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 d8391519b55ef..f93704b15c69b 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: 2023-02-09 +date: 2023-02-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 3f0e9e903929d..eda49a32dd594 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 8b199d3aaa8c4..bfde18fede347 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index bbb632cd9319b..ebfce0df30208 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: 2023-02-09 +date: 2023-02-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 ae3b94567492e..7584d95d31ff1 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: 2023-02-09 +date: 2023-02-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 d7fbdacbcf227..9b508f9ec96d4 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: 2023-02-09 +date: 2023-02-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 b2ded279c4069..a7f45008e0a4d 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: 2023-02-09 +date: 2023-02-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 7562ee8a0a120..af28b8b60ca82 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: 2023-02-09 +date: 2023-02-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 34a959b95d400..9c215841afd72 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: 2023-02-09 +date: 2023-02-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_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index e8cee297e6934..34a07d17365e1 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 61a6ef53f7377..5f9e5288d299d 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: 2023-02-09 +date: 2023-02-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 bfc8c34f83160..581b2e9968416 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index a91a3806d43eb..981a7b6414e83 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index c3418cdc2f438..42dee5ceabad3 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: 2023-02-09 +date: 2023-02-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 d3c08a5b2b8aa..a214dc1551142 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index eedcf063d0589..167d0d3adabde 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 5631e1f3546c9..a2711a95f89ce 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index bf53db69ed4f0..e4d8e38322867 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index a151c02cc8f53..a683165f36adf 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: 2023-02-09 +date: 2023-02-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 006dbc4226d45..05e4a20ce2855 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: 2023-02-09 +date: 2023-02-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 e1fbb08aae34f..69d9c1bb88079 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: 2023-02-09 +date: 2023-02-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 ab31ba40a75ca..aaa7d3dfe410d 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: 2023-02-09 +date: 2023-02-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 ce89d339d87ea..d5ed84349065b 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: 2023-02-09 +date: 2023-02-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_code_editor.mdx b/api_docs/kbn_code_editor.mdx index b50f154c020d2..6296147f32509 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mocks.mdx b/api_docs/kbn_code_editor_mocks.mdx index 6d4c9e940f521..3073334903b20 100644 --- a/api_docs/kbn_code_editor_mocks.mdx +++ b/api_docs/kbn_code_editor_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mocks title: "@kbn/code-editor-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index b025e981b9d06..4a15048edee56 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: 2023-02-09 +date: 2023-02-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 7107b4df60c49..a3a7830383ce0 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: 2023-02-09 +date: 2023-02-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 73d7e9d8f6656..14f416ddaf4b0 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: 2023-02-09 +date: 2023-02-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 6ff4154a7eea2..f3a562b3449a9 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 86a6b6261406d..5b096f285114b 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index 7fa19f018859a..e778b00941e6f 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 06fcf260682b8..22f2ac6d8c797 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: 2023-02-09 +date: 2023-02-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 2538c44be6f2c..e5b9e4f860720 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: 2023-02-09 +date: 2023-02-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 6d661dd9f86d4..d7f616db83efa 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: 2023-02-09 +date: 2023-02-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 c9dc54bc78c7e..e805bc50ca55b 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: 2023-02-09 +date: 2023-02-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 2188c1b2e0c55..4e99017ddc288 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: 2023-02-09 +date: 2023-02-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 f21396d3a1bbf..5978b1a0e5229 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: 2023-02-09 +date: 2023-02-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 2f63adf19265a..78aa50d3861d1 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: 2023-02-09 +date: 2023-02-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 7c6ac5c8a0cb0..d4738bbc59d0d 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: 2023-02-09 +date: 2023-02-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 ff0cbb7d255e0..01e4dea874727 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: 2023-02-09 +date: 2023-02-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 360c7c903aeb6..c4d91ac4006eb 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: 2023-02-09 +date: 2023-02-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_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index aa981fb786ecd..13b4920b62505 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index 1f0d7bcef399d..2766afdb5e3be 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 12d84443ca291..2998c05c621af 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 27e60987112cd..52d9099861e75 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: 2023-02-09 +date: 2023-02-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.mdx b/api_docs/kbn_core_base_common.mdx index 9ffe894ec230c..0c1eb2c3d992c 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: 2023-02-09 +date: 2023-02-10 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 95b9e142ba855..3e270adb9dcd6 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: 2023-02-09 +date: 2023-02-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 5e623b14ac9d1..96ad98af37868 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: 2023-02-09 +date: 2023-02-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 8ee0f28ccf849..b99b2504be070 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: 2023-02-09 +date: 2023-02-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 7d6c00d91ecae..82a59586b1f93 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: 2023-02-09 +date: 2023-02-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 44b0244ef8f27..69a160528387d 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: 2023-02-09 +date: 2023-02-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 b2213e79d57f0..fa0c08e7555d6 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: 2023-02-09 +date: 2023-02-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 327a4b26f56a0..fc8fd1ef56414 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: 2023-02-09 +date: 2023-02-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 7679d6f7c223c..db64749d83e7b 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: 2023-02-09 +date: 2023-02-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 57684d01cbaed..5acd6d9790a7c 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: 2023-02-09 +date: 2023-02-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_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 7e244eda410e0..5ac0468a7dd32 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index 2b54a9d630d3a..c5a15d79027b8 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 3ad3d101dde2b..a1ef18b0db794 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 3a176e740c0f0..a391a7e9e280c 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 64f01c4873931..5e312bd232994 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index f765896d9854e..9dee117c26631 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index b2872d2ea208c..73575460adc6f 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 3e7fa67fb9f45..da54435a8d370 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: 2023-02-09 +date: 2023-02-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 054585c3e0315..738cf8d3d1875 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: 2023-02-09 +date: 2023-02-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 3c224f0e7fb99..e62e363fb1ee8 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: 2023-02-09 +date: 2023-02-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 b516573cefbb0..3fdba744d340c 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: 2023-02-09 +date: 2023-02-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 027a69083553d..43a43a8e6a806 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: 2023-02-09 +date: 2023-02-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 adf408bdd9f54..99257a2eb484a 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: 2023-02-09 +date: 2023-02-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 8efd51cea0f5e..b3bf5ee524785 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: 2023-02-09 +date: 2023-02-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 f1209e37043d8..7ce4d52b52482 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: 2023-02-09 +date: 2023-02-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 a8adf40d56173..b32214b021e28 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: 2023-02-09 +date: 2023-02-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 5a632cb7ebdc5..cfee5e5a5aa17 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: 2023-02-09 +date: 2023-02-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 707d98e64be8f..bf804ce850338 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: 2023-02-09 +date: 2023-02-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 3fe555ec14d70..6c10970d39108 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: 2023-02-09 +date: 2023-02-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 23e7bedadbe97..4316bf7558d45 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: 2023-02-09 +date: 2023-02-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 96e381ce4db6b..8823178ebe33a 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: 2023-02-09 +date: 2023-02-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 1286a66c618d5..1d4512c2f48e9 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: 2023-02-09 +date: 2023-02-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 2324ebcff5105..f148d9e5951ac 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: 2023-02-09 +date: 2023-02-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 ba17b696bb4d7..3e22a8a0f24b9 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: 2023-02-09 +date: 2023-02-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 e79ad30b396c0..45311ed996759 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: 2023-02-09 +date: 2023-02-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 7fe72a60b5f96..435dfd14bb07c 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: 2023-02-09 +date: 2023-02-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 ae8465f353435..6fcff4718bd49 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: 2023-02-09 +date: 2023-02-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 3314084d001b6..9abf4ca5121f6 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: 2023-02-09 +date: 2023-02-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 995ea6a8af5a3..4c3de6ab42dcb 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: 2023-02-09 +date: 2023-02-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 6584fc965104f..ad976577a6979 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: 2023-02-09 +date: 2023-02-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 501c1ac1bcd7f..144c0f61d83b0 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: 2023-02-09 +date: 2023-02-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 68e3ef5d1419a..6d7740924b8a1 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: 2023-02-09 +date: 2023-02-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 cdc8f64f21a85..fbf8e28ba4ed1 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: 2023-02-09 +date: 2023-02-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 6a2d4b0ddcdf5..045a9e4e78ef2 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: 2023-02-09 +date: 2023-02-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 98b29a18025b2..9471aab4fdedc 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: 2023-02-09 +date: 2023-02-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 7aca48a031e2b..5d8bef0b1d572 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: 2023-02-09 +date: 2023-02-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 f2cd9f599d087..b8c8c8efd0770 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: 2023-02-09 +date: 2023-02-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 6fac263c6ccb6..dbe138734b756 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: 2023-02-09 +date: 2023-02-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 dfcd87837b111..bc15bdff6d726 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: 2023-02-09 +date: 2023-02-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_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index e7f64a5ac292e..18b7053e8c023 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 56ed8ac4f3bbd..ac9b44e3b0dd2 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index a2da7c9c7f95e..a60de331b057d 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 28fcf319c1d0c..51304a73ec339 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_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 00efc812fc790..2af8c7c3e8b28 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: 2023-02-09 +date: 2023-02-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 e17bbd3cdba5a..07ca38d498ff9 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: 2023-02-09 +date: 2023-02-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 1410e5cdb37e7..8c465a7bdd71b 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: 2023-02-09 +date: 2023-02-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 80bcba4dd03f5..cc3f560adc9ac 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: 2023-02-09 +date: 2023-02-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 e38ea00d22a4a..f22ea1e8a35bd 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: 2023-02-09 +date: 2023-02-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 4c616ddd9ee9b..822d2f166c0c8 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: 2023-02-09 +date: 2023-02-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 888511ffd8d13..c46a1f0cf5d7a 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: 2023-02-09 +date: 2023-02-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 dedbaec367b49..8ae3a29c88512 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: 2023-02-09 +date: 2023-02-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 c39b5e2d87b03..02a15915d4a32 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: 2023-02-09 +date: 2023-02-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 00f2fa9f04acd..93b1376835929 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: 2023-02-09 +date: 2023-02-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_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index a8d535907e151..0801e2bb86b06 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: 2023-02-09 +date: 2023-02-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 0c796992949d0..188248307a24b 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: 2023-02-09 +date: 2023-02-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 34518c6eef145..ca4b99e39e9cc 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: 2023-02-09 +date: 2023-02-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_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index bbf007eaf59da..7a1bea1769527 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index b1d51c5ec9ca7..d5fe0945d5cd1 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index ed3068d6e58f8..79828678d7065 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index 456eea26469f2..02cee380fa424 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 5ee164de272d5..315baf0311b3c 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index e5b2d949422b8..bba542b084287 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 44db646d5f730..eecbfd3dec7a5 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: 2023-02-09 +date: 2023-02-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 8311c18cefaa2..11854fab1aaf0 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: 2023-02-09 +date: 2023-02-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 f2f86c3c4f636..c2facbf7f8833 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: 2023-02-09 +date: 2023-02-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 a695b1f82bb66..a595553612785 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: 2023-02-09 +date: 2023-02-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 73a8a1fe6a57f..0584c1b389c3e 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: 2023-02-09 +date: 2023-02-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 626b47a7c19bc..694dcd1b322fa 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: 2023-02-09 +date: 2023-02-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 d265262246c8f..9f6425b0dd4e3 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: 2023-02-09 +date: 2023-02-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 b4cdb5b1dcf97..901cdf72a343b 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: 2023-02-09 +date: 2023-02-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 584fadf8344c6..82732b6d90700 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: 2023-02-09 +date: 2023-02-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 918b700e3bbc5..03dde3bbdea82 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: 2023-02-09 +date: 2023-02-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 6f77323d65f23..6755f44f8d26b 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: 2023-02-09 +date: 2023-02-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 2bffba7080557..f34202a6de414 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: 2023-02-09 +date: 2023-02-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 e3d4bebbabcb8..a2a27e8f2870a 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: 2023-02-09 +date: 2023-02-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 e044e50976035..d0df477643d47 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: 2023-02-09 +date: 2023-02-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 b39d40dc50203..c61332a119b52 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: 2023-02-09 +date: 2023-02-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 19be5ce24276d..bc698545a2b8b 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: 2023-02-09 +date: 2023-02-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 8d318877f20f2..82f2404de2e28 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: 2023-02-09 +date: 2023-02-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 f8ec446b6f96b..9cc1684418794 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: 2023-02-09 +date: 2023-02-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_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 05c630e737891..b0c87cb757da3 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index c1506289e0898..b91b4ee04e704 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 94d0db1d25b86..7950f477c91eb 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 54ccc5c6f8d04..fec7bc5a2e147 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 98a746c8b65e9..40fbd9fcdbf92 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: 2023-02-09 +date: 2023-02-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 030f462d796cc..4242d50341690 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: 2023-02-09 +date: 2023-02-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 715341c690ed2..5e332ecf40237 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: 2023-02-09 +date: 2023-02-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_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index e701321b8a419..e667c77ab4255 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index 548aed514df97..710ed1d751158 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index 7c9ff58e5f098..b07fa5b73f6fe 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.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 785a2fccacfac..5b203030c84d7 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: 2023-02-09 +date: 2023-02-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 66c97e14be2af..0e15728262ea7 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: 2023-02-09 +date: 2023-02-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 022d88ddd09e8..c5e127e8b4b1f 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: 2023-02-09 +date: 2023-02-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 2eb8db148afcf..99595c47ae688 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: 2023-02-09 +date: 2023-02-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 d67e126e2fabe..fd312b1d23220 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: 2023-02-09 +date: 2023-02-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 3fa89352bec7e..ebadfb06bb71b 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: 2023-02-09 +date: 2023-02-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 0d02c0b3acc06..0c306144b6447 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: 2023-02-09 +date: 2023-02-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 d912da3aac01b..d2e53f96fac42 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: 2023-02-09 +date: 2023-02-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 a82d2265ff9f1..1e94d77542ecd 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: 2023-02-09 +date: 2023-02-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 441ab73b75b7b..7fb4b6a4cb1f5 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: 2023-02-09 +date: 2023-02-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 76b62d19981b7..4f6602ee9309f 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: 2023-02-09 +date: 2023-02-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 757865166ba24..f7607e306f684 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: 2023-02-09 +date: 2023-02-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 857b89e1eab76..e402e16c81e26 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: 2023-02-09 +date: 2023-02-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 fee43d4cebbe6..96749ed6a6e8f 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: 2023-02-09 +date: 2023-02-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 ac2d200c35b27..1212b1e073d7d 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: 2023-02-09 +date: 2023-02-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 32735b6dc5b99..74920b54cc250 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: 2023-02-09 +date: 2023-02-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 b6654eddc2d75..77554c446e127 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: 2023-02-09 +date: 2023-02-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 42b5e22e54601..12344c32b8e18 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: 2023-02-09 +date: 2023-02-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.mdx b/api_docs/kbn_core_status_common.mdx index c490e15d7aef0..454f46f01143f 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: 2023-02-09 +date: 2023-02-10 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 481d63a5b7c7f..3f572b23bc13e 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: 2023-02-09 +date: 2023-02-10 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 54821cc75611c..ba409c83b0552 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: 2023-02-09 +date: 2023-02-10 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 990e9ec7103cd..6cbc5827a9971 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: 2023-02-09 +date: 2023-02-10 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 770fb68ffe866..7ead48197a8e6 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: 2023-02-09 +date: 2023-02-10 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 5a4d0787673ef..fa5f8f5c03b44 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: 2023-02-09 +date: 2023-02-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 aa822456afc13..2fe6241f81e3c 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: 2023-02-09 +date: 2023-02-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_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 7f4615e1fb493..63c205be83b39 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 95c637ea21bcc..60bfcd40ca115 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index e490bfaf7a6ce..7b3271406c297 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 7d1190378e757..33f5144d8bac1 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: 2023-02-09 +date: 2023-02-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 a4beefa2e4c3b..606b06f34e207 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: 2023-02-09 +date: 2023-02-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 35a50119988a1..abd7608e37b8f 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: 2023-02-09 +date: 2023-02-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 2fd92bc8bfe85..e7d452715a65e 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: 2023-02-09 +date: 2023-02-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 5c177242b7368..bfccbfadcf983 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: 2023-02-09 +date: 2023-02-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 b16af749187ee..2cdb9d5dee404 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: 2023-02-09 +date: 2023-02-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 cd4c1af7dc6fd..36e42c45862cf 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: 2023-02-09 +date: 2023-02-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_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index ca84c0bd80024..6bd7e4e29475e 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index fe2d99129a8df..9630f5384cecd 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index e8155a46d980f..ea038cbe60a0e 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 016f3ced7db02..0aa59796dc1e5 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: 2023-02-09 +date: 2023-02-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 ceee82a34d4ce..817b40179fa9c 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: 2023-02-09 +date: 2023-02-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 2da89ace327bf..5a5f668012c87 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: 2023-02-09 +date: 2023-02-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 38862eea22ae7..b682d0606a711 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: 2023-02-09 +date: 2023-02-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 b0dcd85946cff..93d00dd678ae2 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index ea5fa70c4cf6f..3a76cdc6caaf1 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index c315293d81416..df509935c41b2 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: 2023-02-09 +date: 2023-02-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 b48ce46ecae06..75e6666fa8433 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: 2023-02-09 +date: 2023-02-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 35db7b9537f10..8aea5deb13944 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: 2023-02-09 +date: 2023-02-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 13eebde1ffd30..d33c2f06c6c16 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: 2023-02-09 +date: 2023-02-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 1ad361f4be3d6..be78c620fcbd4 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: 2023-02-09 +date: 2023-02-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.devdocs.json b/api_docs/kbn_doc_links.devdocs.json index 5c2b615b39011..23239d0dde487 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -300,7 +300,7 @@ "label": "enterpriseSearch", "description": [], "signature": [ - "{ readonly apiKeys: string; readonly behavioralAnalyticsEvents: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly connectorsMongoDB: string; readonly connectorsMySQL: string; readonly connectorsWorkplaceSearch: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly deployTrainedModels: string; readonly documentLevelSecurity: string; readonly engines: string; readonly ingestPipelines: string; readonly languageAnalyzers: string; readonly languageClients: string; readonly licenseManagement: string; readonly machineLearningStart: string; readonly mailService: string; readonly start: string; readonly syncRules: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" + "{ readonly apiKeys: string; readonly behavioralAnalytics: string; readonly behavioralAnalyticsEvents: string; readonly bulkApi: string; readonly configuration: string; readonly connectors: string; readonly connectorsMongoDB: string; readonly connectorsMySQL: string; readonly connectorsWorkplaceSearch: string; readonly crawlerManaging: string; readonly crawlerOverview: string; readonly deployTrainedModels: string; readonly documentLevelSecurity: string; readonly engines: string; readonly ingestPipelines: string; readonly languageAnalyzers: string; readonly languageClients: string; readonly licenseManagement: string; readonly machineLearningStart: string; readonly mailService: string; readonly start: string; readonly syncRules: string; readonly troubleshootSetup: string; readonly usersAccess: string; }" ], "path": "packages/kbn-doc-links/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 41d47fc9cbc23..c643bdc445ab2 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: 2023-02-09 +date: 2023-02-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 3b03066ef17c7..2f12531395952 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: 2023-02-09 +date: 2023-02-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 3c84ccf2edcbc..db93f87bea825 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index 2410dc4c2bf86..aba8d038cb73a 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index f3211aa05bce2..6217606074c79 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 9b0cbfdbff84c..e2f91b742a825 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 258a055c5b16a..af057ea2534fa 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: 2023-02-09 +date: 2023-02-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 2a5b9034fa94d..3b7169527a87f 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: 2023-02-09 +date: 2023-02-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 92de37768d5f4..7892764e813ef 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index d4fe9208d6cdd..59115067e1b08 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 834ce9d932fa0..e5aeb887a7ff4 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: 2023-02-09 +date: 2023-02-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 c94e63827cc58..eebddceb30f83 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: 2023-02-09 +date: 2023-02-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 e101f0b64ba3c..f88b620a06115 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: 2023-02-09 +date: 2023-02-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_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index f9aaf97d778a1..5bd55bdc41f8a 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 08d0e2b53981e..391c127c624d5 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 4f5e2244b9af8..05710248ba4a0 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 550294f3003eb..d23057a3d417f 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: 2023-02-09 +date: 2023-02-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 5253d790cf715..a4b4bb01f3474 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 14a9bc3db4b8f..fa2dedacd0c24 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index f3877c9ca47ab..5b80547414e12 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: 2023-02-09 +date: 2023-02-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 28cc210e1dfb7..f16c656b5ea27 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: 2023-02-09 +date: 2023-02-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 4c286cf1c1ea3..36fd56789ac61 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 90b3450bd249f..9ff0cf14779af 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index ac67833d43aa5..9785e0f158be0 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: 2023-02-09 +date: 2023-02-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 ae7e83a05590f..81870ba56f63c 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: 2023-02-09 +date: 2023-02-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 97fd671347132..b2c89c4dbb6f4 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: 2023-02-09 +date: 2023-02-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 e8c3d5d01de41..aea018e1516bb 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 3f6471d57e6b6..b39b36a91d531 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 6481c0a1e2390..e093289b25a09 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index ff4571e9fcdd7..c4072f7a7aab3 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: 2023-02-09 +date: 2023-02-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_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index f34c8b3eeab0a..587f7e3a3fdab 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 8985fc36d4bc2..1010676db999a 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: 2023-02-09 +date: 2023-02-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 e00c5556739e0..53122432106e5 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: 2023-02-09 +date: 2023-02-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 932fdc5dd4efc..3618480cde753 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: 2023-02-09 +date: 2023-02-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 84b28aa06d027..d52026e93f78a 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: 2023-02-09 +date: 2023-02-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 8fe17a16db9b9..788ea5dd1d91c 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: 2023-02-09 +date: 2023-02-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_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 353fd6a5872c3..09f670b06932d 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index 8bce6576342e7..1c5401948e78e 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 27a7fdc841324..f49cb1e7c151b 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: 2023-02-09 +date: 2023-02-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_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index e33bcd06b8e91..47b1bfcf06893 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 80bc0ef9fc8e5..299a7eb1c1916 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 4a21fc7bf810a..62a4121cbe495 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index d2e6035fc2b90..5c8d0cd19eb4d 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: 2023-02-09 +date: 2023-02-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_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 9f52996cbd45e..fdb5493df9f1e 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 7d62874927493..3088aea91b3f5 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: 2023-02-09 +date: 2023-02-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 308d0baa4effd..fb8f696aadda4 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: 2023-02-09 +date: 2023-02-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 0b64e9481b32b..dda0b498e1736 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: 2023-02-09 +date: 2023-02-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_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index f140dba6cb8d9..bcc16917cdf5e 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 38a2d3e427bb0..9d078fa2b08fc 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: 2023-02-09 +date: 2023-02-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 35fc81a71256b..eae74d8d800ae 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: 2023-02-09 +date: 2023-02-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 fe8273bbd423c..40002666bb01b 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: 2023-02-09 +date: 2023-02-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 79911ead0f244..ce1b1a387f3c4 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index e8d3f3f9daec4..3c6c6192016e9 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 69acca6028c2d..5607b3ca063c2 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index 8a4490fbd1bb0..56520ef8f6998 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index d2bd06b06f64c..e3bcfe1958fca 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: 2023-02-09 +date: 2023-02-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_rison.mdx b/api_docs/kbn_rison.mdx index f4029012603aa..c7df088b68cef 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index aab2f99a8cfbc..c5753fc6e1d46 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: 2023-02-09 +date: 2023-02-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 df28172dd30ae..aa6f942020cb3 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 37e09bd98a203..bec8b9ee0896e 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 27fb2dad6edb7..610db1990630d 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: 2023-02-09 +date: 2023-02-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_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 356d752d3d647..d429d390b67c6 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 5c92dd9a38c57..c19757c47ddc9 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: 2023-02-09 +date: 2023-02-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 78c35c9ee9a4d..42c88015bab88 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: 2023-02-09 +date: 2023-02-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 cdf71ed0d4f9c..3dc95951689a9 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: 2023-02-09 +date: 2023-02-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 4600e75b1d36a..1afb4ed6b2bf9 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: 2023-02-09 +date: 2023-02-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 bee142e738c83..3f091dd51e4c6 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: 2023-02-09 +date: 2023-02-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 4b00af140be54..bf999ca1ad812 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: 2023-02-09 +date: 2023-02-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 42c6c99bf8d18..a5f7a080dee86 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: 2023-02-09 +date: 2023-02-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 3249a38a259de..01bf385fbfbc4 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: 2023-02-09 +date: 2023-02-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 caa0d5e2e0041..e47a63225ba96 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: 2023-02-09 +date: 2023-02-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 55ee9049d3558..f108c6bc0090c 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: 2023-02-09 +date: 2023-02-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 32efc033ddfb7..98336b4853d6a 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: 2023-02-09 +date: 2023-02-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 af0f8e763b359..34ae37e2286fc 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: 2023-02-09 +date: 2023-02-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 e63cbfca53d01..c00570a3b6cd3 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: 2023-02-09 +date: 2023-02-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 cff861f8c3b4a..3f0441856f4b0 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: 2023-02-09 +date: 2023-02-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 7d5b0ab7d52e6..8d150c93139ca 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: 2023-02-09 +date: 2023-02-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_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 97ffdae80e991..bed72b71fd958 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index 172bc06c16900..4c6fc441aa94a 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index b1c4117179d7a..401ff93d1e581 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.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 8420fe32efc0b..5d95839779ba0 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: 2023-02-09 +date: 2023-02-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 0db02d3d7ff77..338ee6aca1a91 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: 2023-02-09 +date: 2023-02-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 8c3a3924fd18c..772418656380c 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: 2023-02-09 +date: 2023-02-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 70d2d2f45bd3f..afab966699b8d 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: 2023-02-09 +date: 2023-02-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_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 4dbda76e66af9..be5345bbd0905 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index b5479e93d8f1e..9276071373d0d 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index a1f054c092124..8645271e6edb4 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index f184a0459cf85..346bd0a8281d1 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 5e3798db23757..ceb369dbdb331 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index f4ef6047745a7..13656a080569b 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 676c13ca41429..84e1ced0f9007 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 8b8197b0ac395..6ca201a3d35ec 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.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 298a7c7ca889b..a3ff8e2728dc0 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: 2023-02-09 +date: 2023-02-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_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 5c11ebbbda753..369163e89a069 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 5a29d4876ef99..ade76ab24a794 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_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 6dfdbebabfd2f..2d6baa42ccd47 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: 2023-02-09 +date: 2023-02-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 11ad2bbc3ed6b..6597690e67c05 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: 2023-02-09 +date: 2023-02-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 fa43ca9d14810..7cb87e2d3b5b0 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: 2023-02-09 +date: 2023-02-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 3ba5e717cf791..e9014b2d0f6d4 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: 2023-02-09 +date: 2023-02-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 ae4880bfdcf3d..e5e99c422e660 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: 2023-02-09 +date: 2023-02-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 38b45bf89741b..32d705c8b4130 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: 2023-02-09 +date: 2023-02-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 98791f7505801..532073fb7603e 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: 2023-02-09 +date: 2023-02-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 3f36c76c24574..6b4db8121128b 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: 2023-02-09 +date: 2023-02-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 fbd31f57a4dcb..9aa872905089e 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: 2023-02-09 +date: 2023-02-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 456e00b1e38b7..af484dd11bb30 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: 2023-02-09 +date: 2023-02-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 2187fd966a9db..2db37c64a142b 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: 2023-02-09 +date: 2023-02-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 706ff965f03f0..8b2092fdbc26c 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: 2023-02-09 +date: 2023-02-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 8c3b656c6b6db..ed3d7af328853 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: 2023-02-09 +date: 2023-02-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_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 0aa7056eefc53..6fc328e844fc6 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 68d5bbedf84b9..e7ee777ba09fe 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: 2023-02-09 +date: 2023-02-10 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 635e5f060a153..d916421f3fe8c 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: 2023-02-09 +date: 2023-02-10 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 9e4dbdbfad0e2..8f7fd814b27ba 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: 2023-02-09 +date: 2023-02-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 cc03b53dd4cc8..af8f194025656 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: 2023-02-09 +date: 2023-02-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 6f1c13d5d4f6d..15fa596451cdf 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: 2023-02-09 +date: 2023-02-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_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index bd6516f4e91e3..90a5e38238131 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 0621fdebcb90e..5e72b2db64db7 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: 2023-02-09 +date: 2023-02-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_std.mdx b/api_docs/kbn_std.mdx index 29aa0a99d1005..4c38d37002351 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: 2023-02-09 +date: 2023-02-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 683d07978df36..7abc81756dd34 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: 2023-02-09 +date: 2023-02-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 d3f607edf5a24..cec8375e0abd4 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: 2023-02-09 +date: 2023-02-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 05d9a6e6f9852..9ab749ad406eb 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: 2023-02-09 +date: 2023-02-10 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 5d4db4230040b..d4200e527823c 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: 2023-02-09 +date: 2023-02-10 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 c84a1c47e1fc1..97b49a912c910 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: 2023-02-09 +date: 2023-02-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_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index a5a29e529e8ea..c89ec16b6c2a8 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 5a0134b680648..82b47dc4c8b9f 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index 1dbb0ff239dbb..7758843572b41 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 3558dc45a296a..40af7e0e01413 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: 2023-02-09 +date: 2023-02-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_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index b11f83fa96950..85b1a67e06254 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 0fe3654193722..df64f61d31034 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index f434286117a22..ee0cdff1d4b37 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: 2023-02-09 +date: 2023-02-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 7ec9258cb47e4..13435308a55b4 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: 2023-02-09 +date: 2023-02-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 a5975d6f8d9fd..eee0faf51b25c 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: 2023-02-09 +date: 2023-02-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 cc570c2eab828..17283fb13d92d 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: 2023-02-09 +date: 2023-02-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 367899e3106be..25836038a8fab 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: 2023-02-09 +date: 2023-02-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 40a228dcf4a26..d18f3e5d52722 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: 2023-02-09 +date: 2023-02-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 0de45e567e136..5a97c24f1c742 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.devdocs.json b/api_docs/kibana_react.devdocs.json index b948b9645cb0b..910974c5da2df 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -1777,6 +1777,106 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "kibanaReact", + "id": "def-public.useGlobalUiSetting", + "type": "Function", + "tags": [], + "label": "useGlobalUiSetting", + "description": [ + "\nReturns the current global UI-settings value.\n\nUsage:\n\n```js\nconst customBranding = useGlobalUiSetting('customBranding:pageTitle');\n```" + ], + "signature": [ + "(key: string, defaultValue?: T | undefined) => T" + ], + "path": "src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "kibanaReact", + "id": "def-public.useGlobalUiSetting.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "kibanaReact", + "id": "def-public.useGlobalUiSetting.$2", + "type": "Uncategorized", + "tags": [], + "label": "defaultValue", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "kibanaReact", + "id": "def-public.useGlobalUiSetting$", + "type": "Function", + "tags": [], + "label": "useGlobalUiSetting$", + "description": [ + "\nReturns a 2-tuple, where first entry is the setting value and second is a\nfunction to update the setting value.\n\nSynchronously returns the most current value of the setting and subscribes\nto all subsequent updates, which will re-render your component on new values.\n\nUsage:\n\n```js\nconst [customBranding, setCustomBranding] = useGlobalUiSetting$('customBranding:pageTitle');\n```" + ], + "signature": [ + "(key: string, defaultValue?: T | undefined) => [T, Setter]" + ], + "path": "src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "kibanaReact", + "id": "def-public.useGlobalUiSetting$.$1", + "type": "string", + "tags": [], + "label": "key", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "kibanaReact", + "id": "def-public.useGlobalUiSetting$.$2", + "type": "Uncategorized", + "tags": [], + "label": "defaultValue", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "src/plugins/kibana_react/public/ui_settings/use_ui_setting.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "kibanaReact", "id": "def-public.useKibana", diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index da6216c838be7..0ea5a5836e40e 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 179 | 1 | 149 | 5 | +| 185 | 1 | 153 | 5 | ## Client diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index cb5a6d05d3a81..7a53b5d8d4f39 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: 2023-02-09 +date: 2023-02-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 fcf7ce7d448a6..3c356c90ff6c2 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: 2023-02-09 +date: 2023-02-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 1825b981306f3..8b65ef6dc11d0 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: 2023-02-09 +date: 2023-02-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 c9b2e2b471fe0..8167aa17c8db6 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: 2023-02-09 +date: 2023-02-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 cafc56d49ac2b..8ed0de035580f 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: 2023-02-09 +date: 2023-02-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 97dae9adc772b..2fa065ef68707 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: 2023-02-09 +date: 2023-02-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 b2199800ff72e..ef7504c61a47b 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: 2023-02-09 +date: 2023-02-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 aa01d48d381e2..e26bba0e76537 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: 2023-02-09 +date: 2023-02-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 a7f2dda676e73..0a71e7117c1e8 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: 2023-02-09 +date: 2023-02-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 0eeb233c423ae..873469672de5f 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: 2023-02-09 +date: 2023-02-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 ab3f2ee2b3655..7c965601e1ae7 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: 2023-02-09 +date: 2023-02-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 fd26294f30a50..4f4eac26093cb 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: 2023-02-09 +date: 2023-02-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 a0be8cb20a113..4a58dd679df2c 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: 2023-02-09 +date: 2023-02-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 72e195ba63805..58685d855e1e1 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: 2023-02-09 +date: 2023-02-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 40b7bd10c2351..3faba613724ca 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 932412724849c..724c5373f8a1b 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index e0d7b8085e7de..ef9e84e05d384 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: 2023-02-09 +date: 2023-02-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 cef70e4d96b0d..9e007f2e17b0a 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: 2023-02-09 +date: 2023-02-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 d9ac9d6f3fdfe..d48f104148bc7 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: 2023-02-09 +date: 2023-02-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 | |--------------|----------|------------------------| -| 572 | 469 | 40 | +| 573 | 469 | 39 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 67438 | 512 | 58435 | 1221 | +| 67446 | 512 | 58441 | 1222 | ## Plugin Directory @@ -47,7 +47,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | cloudLinks | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | Adds the links to the Elastic Cloud console | 0 | 0 | 0 | 0 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | The cloud security posture plugin | 17 | 0 | 2 | 2 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 13 | 0 | 13 | 1 | -| | [@elastic/kibana-global-experience](https://github.com/orgs/elastic/teams/kibana-global-experience) | Content management app | 22 | 0 | 22 | 1 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Content management app | 22 | 0 | 22 | 1 | | | [@elastic/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 | 270 | 0 | 266 | 9 | | crossClusterReplication | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | customBranding | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Enables customization of Kibana | 0 | 0 | 0 | 0 | @@ -108,7 +108,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | - | 123 | 2 | 96 | 4 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides UI and APIs for the interactive setup mode. | 28 | 0 | 18 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 179 | 1 | 149 | 5 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 185 | 1 | 153 | 5 | | kibanaUsageCollection | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/kibana-app-services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 609 | 3 | 416 | 9 | | | [@elastic/awp-viz](https://github.com/orgs/elastic/teams/awp-viz) | - | 3 | 0 | 3 | 1 | @@ -130,7 +130,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/observability-ui](https://github.com/orgs/elastic/teams/observability-ui) | - | 614 | 43 | 608 | 32 | | | [@elastic/security-defend-workflows](https://github.com/orgs/elastic/teams/security-defend-workflows) | - | 24 | 0 | 24 | 7 | | painlessLab | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | -| | [@elastic/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). | 217 | 7 | 161 | 11 | +| | [@elastic/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). | 219 | 7 | 163 | 12 | | | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 15 | 2 | 15 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 4 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 36 | 0 | 16 | 0 | diff --git a/api_docs/presentation_util.devdocs.json b/api_docs/presentation_util.devdocs.json index af1a636532a0d..7f53e919c56ab 100644 --- a/api_docs/presentation_util.devdocs.json +++ b/api_docs/presentation_util.devdocs.json @@ -659,6 +659,43 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "presentationUtil", + "id": "def-public.FloatingActions", + "type": "Function", + "tags": [], + "label": "FloatingActions", + "description": [], + "signature": [ + "({ className, actions, isEnabled, usingTwoLineLayout, children, }: React.PropsWithChildren<", + "FloatingActionsProps", + ">) => JSX.Element" + ], + "path": "src/plugins/presentation_util/public/components/floating_actions/floating_actions.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "presentationUtil", + "id": "def-public.FloatingActions.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n className = '',\n actions,\n isEnabled,\n usingTwoLineLayout,\n children,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<", + "FloatingActionsProps", + ">" + ], + "path": "src/plugins/presentation_util/public/components/floating_actions/floating_actions.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "presentationUtil", "id": "def-public.getContextProvider", diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 0ce272912261a..6d65534e27ed8 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kib | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 217 | 7 | 161 | 11 | +| 219 | 7 | 163 | 12 | ## Client diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 8436c1709fd7a..16c373e369bcc 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 3fca7bde8dc82..94bfa8b4cb556 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: 2023-02-09 +date: 2023-02-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 8a92185166d9a..0e7c6579fe008 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: 2023-02-09 +date: 2023-02-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 db5781ec3bd6d..110b5ba2dcc31 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: 2023-02-09 +date: 2023-02-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 c602a2ac3769c..9f2252a55c369 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: 2023-02-09 +date: 2023-02-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 72b8bc491bad8..6d94bc04ac708 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: 2023-02-09 +date: 2023-02-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 9af6dfde9f125..8648aed4a2746 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: 2023-02-09 +date: 2023-02-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 705613eb031e1..63cc51cd24084 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: 2023-02-09 +date: 2023-02-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 6ac097931bf56..26f406bef03b8 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: 2023-02-09 +date: 2023-02-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 3e350c2cd90cc..674c3199aa92d 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: 2023-02-09 +date: 2023-02-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 9e33423216039..2ba916ec10150 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: 2023-02-09 +date: 2023-02-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 4530aa518729f..82518084c529d 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: 2023-02-09 +date: 2023-02-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 1617043e8b03c..5a839eaacf1a7 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: 2023-02-09 +date: 2023-02-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 d6c4ccc55cbe4..42bdb6b49fbaa 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: 2023-02-09 +date: 2023-02-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 d42dd6e0ef2b6..8751084366ea5 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: 2023-02-09 +date: 2023-02-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 15f1bae9af02e..4ec1e8a1df99e 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: 2023-02-09 +date: 2023-02-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 243c35feb063d..b34621cbf4f38 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: 2023-02-09 +date: 2023-02-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 7a4ef96bf4521..762c12fa64374 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: 2023-02-09 +date: 2023-02-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 12272ab51b9b0..83f5dc276d612 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: 2023-02-09 +date: 2023-02-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 67bf4a1a7044b..705c199c30486 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: 2023-02-09 +date: 2023-02-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 e1b1e6c0a1da2..f7e7d81f90daf 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 18d368365f5dc..320891d917333 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index edfc1a714c3ff..11e483e12092a 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: 2023-02-09 +date: 2023-02-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 8b9049ca29161..2e5880b424317 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: 2023-02-09 +date: 2023-02-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 3501ad0c8825e..2550a0d139f12 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: 2023-02-09 +date: 2023-02-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 1150ed5db1314..106a91cba317d 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: 2023-02-09 +date: 2023-02-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 443d4e36e6457..d2c8f9cc322a3 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: 2023-02-09 +date: 2023-02-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 f795f1a5d4ab3..a48f3a23fa028 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: 2023-02-09 +date: 2023-02-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 bbcb015d68287..4a214e7868b38 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: 2023-02-09 +date: 2023-02-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 d8fa7902786e7..2beeac494a9d7 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: 2023-02-09 +date: 2023-02-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 413dde43aea53..1032839989818 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: 2023-02-09 +date: 2023-02-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 51862d2472f3a..12ccfa49e1bb3 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: 2023-02-09 +date: 2023-02-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 f44bc12f4a093..424ed0aeae5a6 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: 2023-02-09 +date: 2023-02-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 af1e457cfdee3..a581a9666cfda 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index c86401ad8ca9d..e4f2abbab19a4 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 696c4df1f8b4d..23be9c1439496 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: 2023-02-09 +date: 2023-02-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 7b199daf55c4a..f20d4d3b20da3 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: 2023-02-09 +date: 2023-02-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 0a6d8d84fb161..133ea111d4fbd 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: 2023-02-09 +date: 2023-02-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 b8c1df917e452..2688502b1c5ff 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: 2023-02-09 +date: 2023-02-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 aeef2a67946c4..2c825bd9397db 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: 2023-02-09 +date: 2023-02-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 c3502c7353208..19d4558a182f9 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: 2023-02-09 +date: 2023-02-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 9930a56bd215d..a531cf76a3ea6 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: 2023-02-09 +date: 2023-02-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 7770d0f3e8330..b4c4063dcb3c5 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: 2023-02-09 +date: 2023-02-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 7071fb3d24df6..61a3fa32b0b94 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: 2023-02-09 +date: 2023-02-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 158807dd36ed9..d3f050412ff47 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: 2023-02-09 +date: 2023-02-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 f4f26ac22e154..d603bfd046c0f 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: 2023-02-09 +date: 2023-02-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 67cb9a798572a..00322ee8d4e1a 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: 2023-02-09 +date: 2023-02-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 0a21bcaafb60b..2d36fa29367e8 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: 2023-02-09 +date: 2023-02-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 dfe7bd4df1ff3..0d9abd57000bd 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: 2023-02-09 +date: 2023-02-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 5550941a6c350..d317e96c78432 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: 2023-02-09 +date: 2023-02-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 6cceb9bcfe2c5..8bc8f2644a826 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: 2023-02-09 +date: 2023-02-10 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 27f112650a5fc85b5ea9efeb1e47c55887d8e824 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Fri, 10 Feb 2023 09:27:28 +0100 Subject: [PATCH 065/203] [Custom branding] Add custom logo to space selector (#150284) ## Summary As part of custom branding, we need to replace all occurrences of Elastic logo with the custom one, when it's set. This PR does that for space selector. Resolves: https://github.com/elastic/kibana/issues/150272 Example of how it might look like: Screenshot 2023-02-06 at 14 59 25 ### Checklist Delete any items that are not applicable to this PR. - [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) ~ - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials~ - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ~- [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/))~ - [X] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) ~- [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ ~- [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))~ ~- [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers)~ ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../space_selector.test.tsx.snap | 56 +++++++++++++++++++ .../space_selector/space_selector.test.tsx | 32 ++++++++++- .../public/space_selector/space_selector.tsx | 26 ++++++++- .../space_selector/space_selector_app.tsx | 1 + x-pack/plugins/spaces/tsconfig.json | 2 + 5 files changed, 114 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap b/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap index 8a24945424379..c6f6584a7144e 100644 --- a/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap +++ b/x-pack/plugins/spaces/public/space_selector/__snapshots__/space_selector.test.tsx.snap @@ -1,5 +1,61 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`it renders with custom logo 1`] = ` +<_KibanaPageTemplate + className="spcSpaceSelector" + data-test-subj="kibanaSpaceSelector" + panelled={true} +> + <_EuiPageEmptyPrompt + className="spcSpaceSelector__pageContent" + > + + + + +

+ +

+ +

+ +

+
+
+ + + + +`; + exports[`it renders without crashing 1`] = ` <_KibanaPageTemplate className="spcSpaceSelector" diff --git a/x-pack/plugins/spaces/public/space_selector/space_selector.test.tsx b/x-pack/plugins/spaces/public/space_selector/space_selector.test.tsx index 7764bcc2c3b9c..57225e0d6473f 100644 --- a/x-pack/plugins/spaces/public/space_selector/space_selector.test.tsx +++ b/x-pack/plugins/spaces/public/space_selector/space_selector.test.tsx @@ -5,8 +5,12 @@ * 2.0. */ +import { EuiImage } from '@elastic/eui'; import React from 'react'; +import { of } from 'rxjs'; +import { customBrandingServiceMock } from '@kbn/core-custom-branding-browser-mocks'; +import { KibanaSolutionAvatar } from '@kbn/shared-ux-avatar-solution'; import { shallowWithIntl } from '@kbn/test-jest-helpers'; import type { Space } from '../../common'; @@ -21,12 +25,32 @@ function getSpacesManager(spaces: Space[] = []) { test('it renders without crashing', () => { const spacesManager = getSpacesManager(); + const customBranding$ = of({}); const component = shallowWithIntl( - + ); expect(component).toMatchSnapshot(); }); +test('it renders with custom logo', () => { + const spacesManager = getSpacesManager(); + const customBranding$ = of({ logo: 'img.jpg' }); + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + expect(component.find(KibanaSolutionAvatar).length).toBe(0); + expect(component.find(EuiImage).length).toBe(1); +}); + test('it queries for spaces when loaded', () => { const spaces = [ { @@ -40,7 +64,11 @@ test('it queries for spaces when loaded', () => { const spacesManager = getSpacesManager(spaces); shallowWithIntl( - + ); return Promise.resolve().then(() => { diff --git a/x-pack/plugins/spaces/public/space_selector/space_selector.tsx b/x-pack/plugins/spaces/public/space_selector/space_selector.tsx index a19745ba2c34e..56bca112a9168 100644 --- a/x-pack/plugins/spaces/public/space_selector/space_selector.tsx +++ b/x-pack/plugins/spaces/public/space_selector/space_selector.tsx @@ -9,6 +9,7 @@ import './space_selector.scss'; import { EuiFieldSearch, + EuiImage, EuiLoadingSpinner, EuiPanel, EuiSpacer, @@ -18,7 +19,9 @@ import { } from '@elastic/eui'; import React, { Component, Fragment } from 'react'; import ReactDOM from 'react-dom'; +import type { Observable, Subscription } from 'rxjs'; +import type { CustomBranding } from '@kbn/core-custom-branding-common'; import type { AppMountParameters, CoreStart } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -34,6 +37,7 @@ import { SpaceCards } from './components'; interface Props { spacesManager: SpacesManager; serverBasePath: string; + customBranding$: Observable; } interface State { @@ -41,10 +45,13 @@ interface State { searchTerm: string; spaces: Space[]; error?: Error; + customLogo?: string; } export class SpaceSelector extends Component { private headerRef?: HTMLElement | null; + private customBrandingSubscription?: Subscription; + constructor(props: Props) { super(props); @@ -67,6 +74,13 @@ export class SpaceSelector extends Component { if (this.state.spaces.length === 0) { this.loadSpaces(); } + this.customBrandingSubscription = this.props.customBranding$.subscribe((next) => { + this.setState({ ...this.state, customLogo: next.logo }); + }); + } + + public componentWillUnmount() { + this.customBrandingSubscription?.unsubscribe(); } public loadSpaces() { @@ -110,7 +124,17 @@ export class SpaceSelector extends Component { - + {this.state.customLogo ? ( + + ) : ( + + )}

Date: Fri, 10 Feb 2023 11:28:41 +0100 Subject: [PATCH 066/203] [APM] Small tweaks for the summary component (#150717) Closes https://github.com/elastic/kibana/issues/147812 Before https://user-images.githubusercontent.com/3369346/217844235-34dbd9c1-a2f3-423c-9a09-c607890fc0f9.mov After https://user-images.githubusercontent.com/3369346/217843740-f1d1ae1a-7b83-45ae-b7f7-8259954bb79b.mov --- .../shared/summary/duration_summary_item.tsx | 17 ++++++++--------- .../summary/error_count_summary_item_badge.tsx | 9 ++------- .../public/components/shared/summary/index.tsx | 6 ++++-- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/apm/public/components/shared/summary/duration_summary_item.tsx b/x-pack/plugins/apm/public/components/shared/summary/duration_summary_item.tsx index 9993fd27b6172..b02b44306566a 100644 --- a/x-pack/plugins/apm/public/components/shared/summary/duration_summary_item.tsx +++ b/x-pack/plugins/apm/public/components/shared/summary/duration_summary_item.tsx @@ -27,16 +27,15 @@ function DurationSummaryItem({ duration, totalDuration, parentType }: Props) { return ( <> - {asDuration(duration)} + + {asDuration(duration)}   + + -   - - - ); } diff --git a/x-pack/plugins/apm/public/components/shared/summary/error_count_summary_item_badge.tsx b/x-pack/plugins/apm/public/components/shared/summary/error_count_summary_item_badge.tsx index 1f339188db149..c08fd0f424617 100644 --- a/x-pack/plugins/apm/public/components/shared/summary/error_count_summary_item_badge.tsx +++ b/x-pack/plugins/apm/public/components/shared/summary/error_count_summary_item_badge.tsx @@ -8,27 +8,22 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiBadge } from '@elastic/eui'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useTheme } from '../../../hooks/use_theme'; interface Props { count: number; } -const Badge = euiStyled(EuiBadge)` - margin-top: 2px; -`; - export function ErrorCountSummaryItemBadge({ count }: Props) { const theme = useTheme(); return ( - + {i18n.translate('xpack.apm.transactionDetails.errorCount', { defaultMessage: '{errorCount, number} {errorCount, plural, one {Error} other {Errors}}', values: { errorCount: count }, })} - + ); } diff --git a/x-pack/plugins/apm/public/components/shared/summary/index.tsx b/x-pack/plugins/apm/public/components/shared/summary/index.tsx index 99c468a740429..619ed1bb8f791 100644 --- a/x-pack/plugins/apm/public/components/shared/summary/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/summary/index.tsx @@ -8,6 +8,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { Fragment } from 'react'; import { Maybe } from '../../../../typings/common'; +import { useBreakpoints } from '../../../hooks/use_breakpoints'; interface Props { items: Array>; @@ -15,12 +16,13 @@ interface Props { function Summary({ items }: Props) { const filteredItems = items.filter(Boolean) as React.ReactElement[]; + const { isSmall } = useBreakpoints(); return ( - + {filteredItems.map((item, index) => ( - {index > 0 && |} + {index > 0 && !isSmall && |} {item} ))} From 2774028ea371c49743ecd42fd8650b4c50eea7bc Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Fri, 10 Feb 2023 11:51:49 +0100 Subject: [PATCH 067/203] [Console] Fix fields suggestions for requests with wildcards and data streams (#150668) ## Summary Resolves https://github.com/elastic/kibana/issues/149496 Fixes autocomplete suggestions for fields when requests contain wildcards or data streams. Wildcards: image Datastreams: image ### How to test #### Datastreams - The easiest way is to deploy Kibana's sample data set "Sample web logs". - Go to the Dev console and type the request ``` GET kibana_sample_data_logs/_search { "aggs": { "my_agg": { "terms": { "field": "", "size": 10 } } } } ``` - Place the cursor and the `fields` value. #### Wildcards - Create a bunch of indices matching a wildcards, e.g. using the following request ``` PUT /my-index- { "mappings": { "properties": { "age": { "type": "integer" }, "email": { "type": "keyword" }, "name": { "type": "text" } } } } ``` - Type some query that requires field value, e.g. ``` GET my-index*/_search { "aggs": { "my_agg": { "terms": { "field": "", "size": 10 } } } } ``` - Place the cursor and the `fields` value. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- .../autocomplete_entities.test.js | 114 +++++++++++++++++- .../lib/autocomplete_entities/data_stream.ts | 7 ++ .../autocomplete_entities/expand_aliases.ts | 16 ++- .../lib/autocomplete_entities/mapping.ts | 13 ++ 4 files changed, 148 insertions(+), 2 deletions(-) diff --git a/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js b/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js index f856ef5750a17..f27b297bd0e0b 100644 --- a/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js +++ b/src/plugins/console/public/lib/autocomplete_entities/autocomplete_entities.test.js @@ -83,6 +83,7 @@ describe('Autocomplete entities', () => { }); expect(mapping.getMappings('index').sort(fc)).toEqual([]); + expect(httpMock.get).not.toHaveBeenCalled(); }); }); @@ -119,6 +120,90 @@ describe('Autocomplete entities', () => { expect(fields).toEqual([{ name: '@timestamp', type: 'date' }]); }); + test('caches mappings for wildcard requests', async () => { + httpMock.get.mockReturnValue( + Promise.resolve({ + mappings: { + 'my-index-01': { mappings: { properties: { '@timestamp': { type: 'date' } } } }, + 'my-index-02': { mappings: { properties: { name: { type: 'keyword' } } } }, + }, + }) + ); + + const autoCompleteContext = {}; + + mapping.getMappings('my-index*', [], autoCompleteContext); + + const fields = await autoCompleteContext.asyncResultsState.results; + + const expectedResult = [ + { + name: '@timestamp', + type: 'date', + }, + { + name: 'name', + type: 'keyword', + }, + ]; + + expect(fields).toEqual(expectedResult); + expect(mapping.getMappings('my-index*', [], autoCompleteContext)).toEqual(expectedResult); + }); + + test('returns mappings for data streams', () => { + dataStream.loadDataStreams({ + data_streams: [ + { name: 'test_index1', indices: [{ index_name: '.ds-index-1' }] }, + { + name: 'test_index3', + indices: [{ index_name: '.ds-index-3' }, { index_name: '.ds-index-4' }], + }, + ], + }); + mapping.loadMappings({ + '.ds-index-3': { + properties: { + first_name: { + type: 'string', + index: 'analyzed', + path: 'just_name', + fields: { + any_name: { type: 'string', index: 'analyzed' }, + }, + }, + last_name: { + type: 'string', + index: 'no', + fields: { + raw: { type: 'string', index: 'analyzed' }, + }, + }, + }, + }, + }); + + const result = mapping.getMappings('test_index3', []); + expect(result).toEqual([ + { + name: 'first_name', + type: 'string', + }, + { + name: 'any_name', + type: 'string', + }, + { + name: 'last_name', + type: 'string', + }, + { + name: 'last_name.raw', + type: 'string', + }, + ]); + }); + test('Multi fields 1.0 style', function () { mapping.loadMappings({ index: { @@ -377,11 +462,38 @@ describe('Autocomplete entities', () => { describe('Data streams', function () { test('data streams', function () { dataStream.loadDataStreams({ - data_streams: [{ name: 'test_index1' }, { name: 'test_index2' }, { name: 'test_index3' }], + data_streams: [ + { name: 'test_index1', indices: [{ index_name: '.ds-index-1' }] }, + { name: 'test_index2', indices: [{ index_name: '.ds-index-2' }] }, + { + name: 'test_index3', + indices: [{ index_name: '.ds-index-3' }, { index_name: '.ds-index-4' }], + }, + ], }); const expectedResult = ['test_index1', 'test_index2', 'test_index3']; expect(dataStream.getDataStreams()).toEqual(expectedResult); + expect(dataStream.perDataStreamIndices).toEqual({ + test_index1: ['.ds-index-1'], + test_index2: ['.ds-index-2'], + test_index3: ['.ds-index-3', '.ds-index-4'], + }); + }); + + test('extracts indices from a data stream', () => { + dataStream.loadDataStreams({ + data_streams: [ + { name: 'test_index1', indices: [{ index_name: '.ds-index-1' }] }, + { + name: 'test_index3', + indices: [{ index_name: '.ds-index-3' }, { index_name: '.ds-index-4' }], + }, + ], + }); + + expect(expandAliases('test_index1')).toEqual('.ds-index-1'); + expect(expandAliases('test_index3')).toEqual(['.ds-index-3', '.ds-index-4']); }); }); }); diff --git a/src/plugins/console/public/lib/autocomplete_entities/data_stream.ts b/src/plugins/console/public/lib/autocomplete_entities/data_stream.ts index 2b65d086aeb13..b46070f77b939 100644 --- a/src/plugins/console/public/lib/autocomplete_entities/data_stream.ts +++ b/src/plugins/console/public/lib/autocomplete_entities/data_stream.ts @@ -11,12 +11,19 @@ import type { IndicesGetDataStreamResponse } from '@elastic/elasticsearch/lib/ap export class DataStream { private dataStreams: string[] = []; + public perDataStreamIndices: Record = {}; + getDataStreams = (): string[] => { return [...this.dataStreams]; }; loadDataStreams = (dataStreams: IndicesGetDataStreamResponse) => { this.dataStreams = (dataStreams.data_streams ?? []).map(({ name }) => name).sort(); + + this.perDataStreamIndices = dataStreams.data_streams.reduce((acc, { name, indices }) => { + acc[name] = indices.map((index) => index.index_name); + return acc; + }, {} as Record); }; clearDataStreams = () => { diff --git a/src/plugins/console/public/lib/autocomplete_entities/expand_aliases.ts b/src/plugins/console/public/lib/autocomplete_entities/expand_aliases.ts index 27f8211f533a9..0a13475227e78 100644 --- a/src/plugins/console/public/lib/autocomplete_entities/expand_aliases.ts +++ b/src/plugins/console/public/lib/autocomplete_entities/expand_aliases.ts @@ -8,10 +8,18 @@ import { getAutocompleteInfo } from '../../services'; -export function expandAliases(indicesOrAliases: string | string[]) { +/** + * Expands provided aliases, data streams and wildcards + * @param indicesOrAliases - single value or an array of indices, aliases and data streams + * @returns {string | string[]} - single index or an array of resolved indices from provided input. + */ +export function expandAliases(indicesOrAliases: string | string[]): string | string[] { // takes a list of indices or aliases or a string which may be either and returns a list of indices // returns a list for multiple values or a string for a single. const perAliasIndexes = getAutocompleteInfo().alias.perAliasIndexes; + const perDataStreamIndices = getAutocompleteInfo().dataStream.perDataStreamIndices; + const perWildcardIndices = getAutocompleteInfo().mapping.perWildcardIndices; + if (!indicesOrAliases) { return indicesOrAliases; } @@ -24,6 +32,12 @@ export function expandAliases(indicesOrAliases: string | string[]) { if (perAliasIndexes[iOrA]) { return perAliasIndexes[iOrA]; } + if (perDataStreamIndices[iOrA]) { + return perDataStreamIndices[iOrA]; + } + if (perWildcardIndices[iOrA]) { + return perWildcardIndices[iOrA]; + } return [iOrA]; }); diff --git a/src/plugins/console/public/lib/autocomplete_entities/mapping.ts b/src/plugins/console/public/lib/autocomplete_entities/mapping.ts index 3c383ca124167..eff644ad94683 100644 --- a/src/plugins/console/public/lib/autocomplete_entities/mapping.ts +++ b/src/plugins/console/public/lib/autocomplete_entities/mapping.ts @@ -108,6 +108,11 @@ export class Mapping implements BaseMapping { */ public perIndexTypes: Record = {}; + /** + * Map of the user-input wildcards and actual indices. + */ + public perWildcardIndices: Record = {}; + private readonly _isLoading$ = new BehaviorSubject(false); /** @@ -181,6 +186,14 @@ export class Mapping implements BaseMapping { autoCompleteContext.asyncResultsState!.isLoading = false; autoCompleteContext.asyncResultsState!.lastFetched = Date.now(); + const mappingsIndices = Object.keys(mapping); + if ( + mappingsIndices.length > 1 || + (mappingsIndices[0] && mappingsIndices[0] !== indices) + ) { + this.perWildcardIndices[indices as string] = Object.keys(mapping); + } + // cache mappings this.loadMappings(mapping); From dbecb5169bb4db120616019df09da2ac5605c8f4 Mon Sep 17 00:00:00 2001 From: Elena Stoeva <59341489+ElenaStoeva@users.noreply.github.com> Date: Fri, 10 Feb 2023 10:56:40 +0000 Subject: [PATCH 068/203] Accept additional dynamic field values for index template (#150543) Fixes https://github.com/elastic/kibana/issues/123809 ## Summary This PR adds support for the `'true'`, `'false'`, and `'runtime'` values for the `dynamic` field of index templates as they are [supported by Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/8.6/dynamic.html#dynamic-parameters). Before these changes, setting one of these values for the `dynamic` field would cause a `MultipleMappingsWarning` message when editing the Mappings section as described in the scenario in https://github.com/elastic/kibana/issues/123809. Regarding the string values `'true'` and `'false'`, according to https://github.com/elastic/elasticsearch-java/issues/139, "Elasticsearch is lenient and happily accepts a string for boolean values", which is why we need to add support for these two values in Kibana. https://user-images.githubusercontent.com/59341489/217516509-88679c38-271c-4c7d-9145-27c7f9cfa8ca.mov ### Checklist - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../constants/parameters_definition.tsx | 8 +++++- .../lib/mappings_validator.test.ts | 27 +++++++++++++++++-- .../mappings_editor/lib/mappings_validator.ts | 9 ++++++- 3 files changed, 40 insertions(+), 4 deletions(-) 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 8c26701498f0d..d108c1427c9d8 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 @@ -683,7 +683,13 @@ export const PARAMETERS_DEFINITION: { [key in ParameterName]: ParameterDefinitio fieldConfig: { defaultValue: true, }, - schema: t.union([t.boolean, t.literal('strict')]), + schema: t.union([ + t.boolean, + t.literal('strict'), + t.literal('true'), + t.literal('false'), + t.literal('runtime'), + ]), }, dynamic_toggle: { fieldConfig: { diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts index 2006f72a7e35d..a929cc9d29d0a 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.test.ts @@ -329,7 +329,7 @@ describe('Properties validator', () => { orientation: 'ccw', boost: 1.5, scaling_factor: 2.5, - dynamic: 'strict', // true | false | 'strict' are allowed + dynamic: 'strict', // true | false | 'strict' | 'true' | 'false' | 'runtime' are allowed enabled: true, format: 'strict_date_optional_time', analyzer: 'standard', @@ -367,16 +367,39 @@ describe('Properties validator', () => { type: 'object', dynamic: false, }, + goodField4: { + type: 'object', + dynamic: 'true', + }, + goodField5: { + type: 'object', + dynamic: 'false', + }, + goodField6: { + type: 'object', + dynamic: 'runtime', + }, }; const { value, errors } = validateProperties(properties as any); - expect(Object.keys(value)).toEqual(['wrongField', 'goodField', 'goodField2', 'goodField3']); + expect(Object.keys(value)).toEqual([ + 'wrongField', + 'goodField', + 'goodField2', + 'goodField3', + 'goodField4', + 'goodField5', + 'goodField6', + ]); expect(value.wrongField).toEqual({ type: 'text' }); // All parameters have been stripped out but the "type". expect(value.goodField).toEqual(properties.goodField); // All parameters are stil there. expect(value.goodField2).toEqual(properties.goodField2); expect(value.goodField3).toEqual(properties.goodField3); + expect(value.goodField4).toEqual(properties.goodField4); + expect(value.goodField5).toEqual(properties.goodField5); + expect(value.goodField6).toEqual(properties.goodField6); const allWrongParameters = Object.keys(properties.wrongField).filter((v) => v !== 'type'); expect(errors).toEqual( diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts index 23528dd103ec0..3691367e4a8f2 100644 --- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts +++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/mappings_validator.ts @@ -207,7 +207,14 @@ export const mappingsConfigurationSchema = t.exact( t.partial({ properties: t.UnknownRecord, runtime: t.UnknownRecord, - dynamic: t.union([t.literal(true), t.literal(false), t.literal('strict')]), + dynamic: t.union([ + t.literal(true), + t.literal(false), + t.literal('strict'), + t.literal('true'), + t.literal('false'), + t.literal('runtime'), + ]), date_detection: t.boolean, numeric_detection: t.boolean, dynamic_date_formats: t.array(t.string), From 486d56b33fcb137f6f2dc62a13acd58ea19a1e00 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Fri, 10 Feb 2023 13:07:23 +0100 Subject: [PATCH 069/203] [Fleet] added more upload tests and openapi (#150743) ## Summary Related to https://github.com/elastic/kibana/issues/148599 Added more integration tests. Added openapi spec. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../plugins/fleet/common/openapi/bundled.json | 194 ++++++++++++------ .../plugins/fleet/common/openapi/bundled.yaml | 152 +++++++++----- .../common/openapi/paths/epm@packages.yaml | 102 ++++++--- .../apis/epm/install_by_upload.ts | 72 ++++++- .../direct_upload_packages/apache-0.1.5.zip | Bin 0 -> 615260 bytes 5 files changed, 378 insertions(+), 142 deletions(-) create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/direct_upload_packages/apache-0.1.5.zip diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index c4082843e25c9..041c757075bbf 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -325,44 +325,120 @@ } } }, - "operationId": "list-all-packages" - }, - "parameters": [ - { - "in": "query", - "name": "excludeInstallStatus", - "schema": { - "type": "boolean", - "default": false + "operationId": "list-all-packages", + "parameters": [ + { + "in": "query", + "name": "excludeInstallStatus", + "schema": { + "type": "boolean", + "default": false + }, + "description": "Whether to exclude the install status of each package. Enabling this option will opt in to caching for the response via `cache-control` headers. If you don't need up-to-date installation info for a package, and are querying for a list of available packages, providing this flag can improve performance substantially." }, - "description": "Whether to exclude the install status of each package. Enabling this option will opt in to caching for the response via `cache-control` headers. If you don't need up-to-date installation info for a package, and are querying for a list of available packages, providing this flag can improve performance substantially." - }, - { - "in": "query", - "name": "prerelease", - "schema": { - "type": "boolean", - "default": false + { + "in": "query", + "name": "prerelease", + "schema": { + "type": "boolean", + "default": false + }, + "description": "Whether to return prerelease versions of packages (e.g. beta, rc, preview) " }, - "description": "Whether to return prerelease versions of packages (e.g. beta, rc, preview) " - }, - { - "in": "query", - "name": "experimental", - "deprecated": true, - "schema": { - "type": "boolean", - "default": false + { + "in": "query", + "name": "experimental", + "deprecated": true, + "schema": { + "type": "boolean", + "default": false + } + }, + { + "in": "query", + "name": "category", + "schema": { + "type": "string" + } + } + ] + }, + "post": { + "summary": "Packages - Install by upload", + "tags": [], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "oneOf": [ + { + "$ref": "#/components/schemas/kibana_saved_object_type" + }, + { + "$ref": "#/components/schemas/elasticsearch_asset_type" + } + ] + } + }, + "required": [ + "id", + "type" + ] + } + }, + "_meta": { + "type": "object", + "properties": { + "install_source": { + "type": "string", + "enum": [ + "upload", + "registry", + "bundled" + ] + } + } + } + }, + "required": [ + "items" + ] + } + } + } } }, - { - "in": "query", - "name": "category", - "schema": { - "type": "string" + "operationId": "install-package-by-upload", + "description": "", + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "content": { + "application/zip": { + "schema": { + "type": "string", + "format": "binary" + } + } } } - ] + } }, "/epm/packages/_bulk": { "post": { @@ -4882,6 +4958,33 @@ "items" ] }, + "kibana_saved_object_type": { + "title": "Kibana saved object asset type", + "type": "string", + "enum": [ + "dashboard", + "visualization", + "search", + "index-pattern", + "map", + "lens", + "ml-module", + "security-rule", + "csp_rule_template" + ] + }, + "elasticsearch_asset_type": { + "title": "Elasticsearch asset type", + "type": "string", + "enum": [ + "component_template", + "ingest_pipeline", + "index_template", + "ilm_policy", + "transform", + "data_stream_ilm_policy" + ] + }, "bulk_install_packages_response": { "title": "Bulk install packages response", "type": "object", @@ -5131,33 +5234,6 @@ "path" ] }, - "kibana_saved_object_type": { - "title": "Kibana saved object asset type", - "type": "string", - "enum": [ - "dashboard", - "visualization", - "search", - "index-pattern", - "map", - "lens", - "ml-module", - "security-rule", - "csp_rule_template" - ] - }, - "elasticsearch_asset_type": { - "title": "Elasticsearch asset type", - "type": "string", - "enum": [ - "component_template", - "ingest_pipeline", - "index_template", - "ilm_policy", - "transform", - "data_stream_ilm_policy" - ] - }, "package_usage_stats": { "title": "Package usage stats", "type": "object", diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 654918ddc265d..576cc240f64bf 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -205,36 +205,82 @@ paths: schema: $ref: '#/components/schemas/get_packages_response' operationId: list-all-packages - parameters: - - in: query - name: excludeInstallStatus - schema: - type: boolean - default: false - description: >- - Whether to exclude the install status of each package. Enabling this - option will opt in to caching for the response via `cache-control` - headers. If you don't need up-to-date installation info for a package, - and are querying for a list of available packages, providing this flag - can improve performance substantially. - - in: query - name: prerelease - schema: - type: boolean - default: false - description: >- - Whether to return prerelease versions of packages (e.g. beta, rc, - preview) - - in: query - name: experimental - deprecated: true - schema: - type: boolean - default: false - - in: query - name: category - schema: - type: string + parameters: + - in: query + name: excludeInstallStatus + schema: + type: boolean + default: false + description: >- + Whether to exclude the install status of each package. Enabling this + option will opt in to caching for the response via `cache-control` + headers. If you don't need up-to-date installation info for a + package, and are querying for a list of available packages, + providing this flag can improve performance substantially. + - in: query + name: prerelease + schema: + type: boolean + default: false + description: >- + Whether to return prerelease versions of packages (e.g. beta, rc, + preview) + - in: query + name: experimental + deprecated: true + schema: + type: boolean + default: false + - in: query + name: category + schema: + type: string + post: + summary: Packages - Install by upload + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + type: object + properties: + id: + type: string + type: + oneOf: + - $ref: '#/components/schemas/kibana_saved_object_type' + - $ref: '#/components/schemas/elasticsearch_asset_type' + required: + - id + - type + _meta: + type: object + properties: + install_source: + type: string + enum: + - upload + - registry + - bundled + required: + - items + operationId: install-package-by-upload + description: '' + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + content: + application/zip: + schema: + type: string + format: binary /epm/packages/_bulk: post: summary: Packages - Bulk install @@ -3055,6 +3101,29 @@ components: $ref: '#/components/schemas/search_result' required: - items + kibana_saved_object_type: + title: Kibana saved object asset type + type: string + enum: + - dashboard + - visualization + - search + - index-pattern + - map + - lens + - ml-module + - security-rule + - csp_rule_template + elasticsearch_asset_type: + title: Elasticsearch asset type + type: string + enum: + - component_template + - ingest_pipeline + - index_template + - ilm_policy + - transform + - data_stream_ilm_policy bulk_install_packages_response: title: Bulk install packages response type: object @@ -3228,29 +3297,6 @@ components: - format_version - download - path - kibana_saved_object_type: - title: Kibana saved object asset type - type: string - enum: - - dashboard - - visualization - - search - - index-pattern - - map - - lens - - ml-module - - security-rule - - csp_rule_template - elasticsearch_asset_type: - title: Elasticsearch asset type - type: string - enum: - - component_template - - ingest_pipeline - - index_template - - ilm_policy - - transform - - data_stream_ilm_policy package_usage_stats: title: Package usage stats type: object diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml index a6332360283bd..d3ef2a279494e 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml @@ -9,31 +9,77 @@ get: schema: $ref: ../components/schemas/get_packages_response.yaml operationId: list-all-packages -parameters: - - in: query - name: excludeInstallStatus - schema: - type: boolean - default: false - description: >- - Whether to exclude the install status of each package. Enabling this option will opt in to - caching for the response via `cache-control` headers. If you don't need up-to-date installation - info for a package, and are querying for a list of available packages, providing this flag can - improve performance substantially. - - in: query - name: prerelease - schema: - type: boolean - default: false - description: >- - Whether to return prerelease versions of packages (e.g. beta, rc, preview) - - in: query - name: experimental - deprecated: true - schema: - type: boolean - default: false - - in: query - name: category - schema: - type: string + parameters: + - in: query + name: excludeInstallStatus + schema: + type: boolean + default: false + description: >- + Whether to exclude the install status of each package. Enabling this option will opt in to + caching for the response via `cache-control` headers. If you don't need up-to-date installation + info for a package, and are querying for a list of available packages, providing this flag can + improve performance substantially. + - in: query + name: prerelease + schema: + type: boolean + default: false + description: >- + Whether to return prerelease versions of packages (e.g. beta, rc, preview) + - in: query + name: experimental + deprecated: true + schema: + type: boolean + default: false + - in: query + name: category + schema: + type: string +post: + summary: Packages - Install by upload + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + items: + type: array + items: + type: object + properties: + id: + type: string + type: + oneOf: + - $ref: ../components/schemas/kibana_saved_object_type.yaml + - $ref: ../components/schemas/elasticsearch_asset_type.yaml + required: + - id + - type + _meta: + type: object + properties: + install_source: + type: string + enum: + - upload + - registry + - bundled + required: + - items + operationId: install-package-by-upload + description: '' + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + requestBody: + content: + application/zip: + schema: + type: string + format: binary \ No newline at end of file diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts index d7c913fc8bc4b..fcf7fdaa4ed81 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts @@ -19,6 +19,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const dockerServers = getService('dockerServers'); + const esClient = getService('es'); const testPkgArchiveTgz = path.join( path.dirname(__filename), @@ -49,8 +50,14 @@ export default function (providerContext: FtrProviderContext) { '../fixtures/direct_upload_packages/apache_invalid_toplevel_mismatch_0.1.4.zip' ); + const testPkgArchiveZipNewer = path.join( + path.dirname(__filename), + '../fixtures/direct_upload_packages/apache-0.1.5.zip' + ); + const testPkgName = 'apache'; const testPkgVersion = '0.1.4'; + const testPkgNewVersion = '0.1.5'; const server = dockerServers.get('registry'); const deletePackage = async (name: string, version: string) => { @@ -68,15 +75,76 @@ export default function (providerContext: FtrProviderContext) { } }); - it('should install a tar archive correctly', async function () { + async function uploadPackage() { const buf = fs.readFileSync(testPkgArchiveTgz); - const res = await supertest + return await supertest .post(`/api/fleet/epm/packages`) .set('kbn-xsrf', 'xxxx') .type('application/gzip') .send(buf) .expect(200); + } + + it('should install a tar archive correctly', async function () { + const res = await uploadPackage(); + expect(res.body.items.length).to.be(30); + }); + + it('should upgrade when uploading a newer zip archive', async () => { + await uploadPackage(); + + const buf = fs.readFileSync(testPkgArchiveZipNewer); + const res = await supertest + .post(`/api/fleet/epm/packages`) + .set('kbn-xsrf', 'xxxx') + .type('application/zip') + .send(buf) + .expect(200); expect(res.body.items.length).to.be(30); + expect(res.body.items.some((item: any) => item.id.includes(testPkgNewVersion))); + + await deletePackage(testPkgName, testPkgNewVersion); + }); + + it('should clean up assets when uninstalling uploaded archive', async () => { + await uploadPackage(); + await deletePackage(testPkgName, testPkgVersion); + + const epmPackageRes = await esClient.search({ + index: '.kibana', + size: 0, + rest_total_hits_as_int: true, + query: { + bool: { + filter: [ + { + term: { + 'epm-packages.name': testPkgName, + }, + }, + ], + }, + }, + }); + const epmPackageAssetsRes = await esClient.search({ + index: '.kibana', + size: 0, + rest_total_hits_as_int: true, + query: { + bool: { + filter: [ + { + term: { + 'epm-packages-assets.package_name': testPkgName, + }, + }, + ], + }, + }, + }); + + expect(epmPackageRes.hits.total).to.equal(0); + expect(epmPackageAssetsRes.hits.total).to.equal(0); }); it('should install a zip archive correctly and package info should return correctly after validation', async function () { diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/direct_upload_packages/apache-0.1.5.zip b/x-pack/test/fleet_api_integration/apis/fixtures/direct_upload_packages/apache-0.1.5.zip new file mode 100644 index 0000000000000000000000000000000000000000..c4b92dcb500a2b39a0f03815352096ee8267876d GIT binary patch literal 615260 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�_!~Y`=FYg~u9eC8ruTC^-);CzS(@h% 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 z zgCz%N+T^|MC&eAcuk<(Y6Vrj_F%$$e0B<9_PsCve{8s-!%~7A&u|tN#JHkgFeWK$} zXTvwX@zR8LoYkD60Fy$9v zFi5-esiy)rNABA7$MDwM?}S$EYU7r>O2)oD?Yt*FDRp(L@0QyCozSnmX#4Kcv9OCQ z_ha%kPYR2(vXS-0{v+D?vPwtp8np1hG3r56s0~Shv~S;jQ)r-UY|@cD6!K@a$4WshB9977#T@z}1qY1Q$>BgeaJ0fI3L z<(%j^+xs5qg?!@%LvHe8N3c$|hn2FA$t}rQ*Cjhy%hY#dFCxf>yPx0fIvS0_k;`s2 zu3uZc0dzpTviFdbk2<)1KiuQuN&zMY60xvfidbOe`nbNh~V=BZubdUbo| zo4Is$;J!Ws(7Yn5^P!SQqPbYo`|N@vIiM z;1l{>p6ohg_o3H6GM4&x2S3CK?rd8qT++74cF8SN`@(tqB3|n7$9CtGM;uFyhQ+!9-^%4c$)~YdrY@%g zS5Fhv!IfjR{tk|~v2j&>l(U`jIB_RK^DONgSJKSFvNU(xp)t+K=ajVdEUtvLGEOPY zOYJU;YxQ!B%^%Q}c~W-%OS;g8GFR$Y%;5FaODrC z$2soldlpvNFvJy>%e?MZ|~#a zWyiyx#Lv1cEd5U3iI;x+dzN--xI9=2Pv1Q~f2J_raVaeOT?;G^ACH#@vrP4qg?Su* zrntDDKRu1~nT4f-JPV_`U8u7X-l&Oy7-GuYBJHrccKt>eR>#3kg{;fslYXb~#LIqr zS{SiqVT?|YFmsY!7k<<9_~3)A9E#Ed5U3({$7KEIwnwQh56AdHFMi@s3Mj+3#9l6Ty{yvhh4G zf2O#&pFe?RT^5#p`+NFiC(-(qtF-H@`p}6ZxD%bgI*zNPbisi2c--=3%fk=;^52IK zKKwBJ>}S6S-+%3Uq0Np9O`-4*LRYU{34i#*2Zq|$HE~|KVr->6_KB8Ak=@gK-HtM98!8H@^9+)Ly0mo{?0Kq>bXnD@pxhoo?R?`QeJG? zwmmFrjW^RFqm)Tl(iXq7xPBSF*)@ccaOsNezKu4}eBxVL zrBCVX@7ZTw>V#pkM*p`_M~f@%c4jxxm1{j_i|os&{JMPYnknyOoGLVGcP6(HpVhAA z<=X9aQ5O%K(k+@A>`AfOtX+6l!iue%b$e{H?etzP`)m_&S9Duqn`~o!F24Wp!%xCr z|Mg$lj!bUQgnu7>bdB-rqnkHrN9G1)QCTjmTf5GVBfs_bZ^NJc*$dV#8s?2{NS}V+ z4TzuCZIx~d@2bWd%~D`CG}c=ivfbsXXWAcij`Mea8ZW31M?p5IKAy|W8Vkp|otKDL z>Aez+^v46M6xQ?gXI?mmd7eJ5^RPT|g!8ce?Q!_d#;XJ)Z0bCor|nO|RD%&Nb!j}_ zv)_&n(J)O>`Yz4I(>!@k(@0_N@6WMdgiBo-kN51i<5ntvR21?}Sf5imoV3$4_)cMb zr_Ny>$Df3$1|wV=Hv69a_Hs~sXpU0~HjkXE1)O2cDG9>@5H6ilnumU>;ZqF;E~(4n zmi;c_TDgp*=Xvs;O(XpVj`MWWcvfcN=P+oJb=603+0YNjw-c!BmYD(}9LCd_M8cPM zcTO~5FbdA$S(twl#@{`je~$$Nj?2dL`2Hk}zh|EwmoV-;jKlmJxWA7VMqHU$-#b9%f7U(5RK3EFS(%I{u!0rnnLg=V2V?-;;q6H;+H?$B{?2 zt~_6Vf{$;Hjj=}KivL7t?s*X3-}A~39G8W89DfqV-?LATOBi<^#$m9ti=NT2a@jLa zgTEVE4ercbDH^+ zaQ>csdR$K{4eKzEGZ`3hE0xjHooSO$JofjwG%qw#j@Vwha4|I3M+GZ%CA`Ps8^IZ@B1$V|<&|tuBr$E0z6z`uF$uOKG>r z>SruG*v$itp(XO!-@QHflXUz&`}B6_c@^7~JZ?$Z@!4M4%G$I}$KglUIX0iVrGT4X z!!Aru|6V+A$&M8l+H_0NHKg`SPrhy2Hrp}SFNH6T9djs38&w8qBK8Vb6sKQD`(AwU z`LJ&7Itw@6pQTHdg{9wEX3_rc?|&NJegGFi=)U_M@$7lCwTC>w=svqc-+1FKJAVAc zjwh;S!7=7TQo#SW|MuT?)8?Y^=$0*})NK;pm}6M1zPMdVUiw|y3_Dd(@L{XeC!>wp zy^cLH%9-8S<@^8={+@l(KiRHZje&+VE~f1f#?yD6@iy)8owxiu%_9#6oHQ!IEKlK5 zZSF%{SKN{w&T;j0Ef3}6Fq9U2!6y+{(fivPOWT}MZ6|e}X7)*# zte<~p^Gw4!%)?F;=4eL#5H5yKTofTq9DTRf74L-geEl1IWXUf^NPb8AB)|vt)e0|x z!m$|MvG)QaJ3}E%xk-d?c*BJiVezvGoSwvECxJIYVAwR^8yNrG0rPYrdb;JW3}*P0 z2G4{gJwNO2+johB^E7$SmV+>kEAc!nF9%!38F=O5syr!6F04QwCXjT{IPxNW7!BHy z$8_RKe#LSKPp5g@*%4_2-0?|io~2!0Ii`Z<&~6leRHJ!;uJ8u<;^0dJ6bb{o-A3g` z@x|mxMAueT*)tFy4{C7EpxpT?TSn5FO8yuxpO3{K#+x&3(pG|NZIjOb#@lL#mt>FS zf{f#@)p3NWa1A;-Ksy*xy|C*cD+jakqf(nh4%z^9&O9?h3qQlF?9?I-oiMzKlFP18 zR-UxUS!x6DJVuzC>U4}jez!D$?$ZRUUK34Z&+I1I^9l{tp%1AI3@ELuQjA@Yy_wr; z7j@g}WXQ7B{ubyc$4w~+`=m@}l^7ch(3&zvS%dDJF*GUy|8rn}oLD?Xq{e zs=pwj+rg!~Wj)z9VJz#BNb!ch?HZutPd7 z`N*nOk_B;$k%vQjTZfF|cZAhz9tkH-oD9GI)o;R`AGU{?_(VY^awqDgBqJ@j457VkPScFkg{N+wD)wU`+4QcRVfQsX{T}J zOA|Q8cHrmtZ#k$ zRfA3ZC${hBrMTL=cfTnzuWF}Rw~mOS0NeW5R(lSppTuF054&VhHk9YO`jOQ-_PaVP zS-K?bIoKIaOM!bs_P1>DNJVPaZKfRGJap`oZmqm(b;fa36khb}D3mFBoQu)Lm&={8 zcmzIxHuRNd3vN#2E&Nzet2CCnpMB+=x^e{=xWW%SX$LkIE@)c}#+(5;0j$uMPz(4u zeQXR^m@{|{6=9-jcAiGu?3~i$p$xFOhCIAoI*ezfIVG^NF=2u$F!F@%*>V_coO4Rz z;HDB+Xzl!$@<*J*#YHBqje5`JeoLWx&(cM>v>cz=F{$| zN9>$Yr@rvzFrE*k^2-V7a@HnT5}xk7;X@|gMYBT39hFIhgZO5299uI5p+l$7gvnuH zRvhFK9>&6GT&y$+0r|OdD8dTL9QiW=#6FINg?S|~c*nu$?3z%09LM$0002M$NklGmoT%4AbIKC=BPvg=97-4G`0%Wq z=7suDowEy-0Wps9VXTq?Bx^a>w6&Xo-#iU0aWryl9oS$`;fftyu@j4fo!V(m2dBD}9hfAa)9(5%QvGM;U`_m?dc32-{qiM?wIgG`@j@AXs_=#KXU7@_ z>fvQ?FNA{!;6axkvGXeJ#$_Pj?T~m)x&VOi7@TKk0LJm-EiO`#$sSn4qWXYIX$)0k zBaK~^HZfBSCe%Z$#!0vNLpO-@b#Bo3cq{j_uSO25 z>h*i{L|5q1g(TSg!m)^fn~Jfk$$E_|c{1i;frc^Lq0WUQNL@p$s%k8cay?1?<)R!5Xy9Bs@hcdzzb*KV|-uz2aR z@aSDFQfUVlw#1mc4#>YvHp4JWK%KN`CplwN6r!{}%Ip21_xUN0ILzhSn0=-Ca8KvU zI)0_jef(w@6v^q;OgbCj%%cOvAhYcu^gp2B|C!e%og6N z6QQ6o>k=j9lSgw4TS&A-bLMc2^I|&xu+OgSU$Hw6+k4Kw?=H4c2r+MU$QaQ@`1D+#a>Jd63KRnNr zmm{B}%#FOv_{YZWiU&Q|VH)QQESyK>7QBFi?@Ig;$KLn@9=YvYjZbuSVcS>!);}J! z=imPLJGm&c6&fNlDK~|Jh-QsW6^md3hISF+!^A0!%7eIeL`JDQj0yrqJO~UaVJas3 z29pn+v{j75lov`3Dvbd`tTfV$yAe=yxZnfkxPqg142~j`T^9I*)Ki)ppVz`4O2g{|9sn1|r^M&^ z{Na2)(^`MtFY6N8aIqdaV{SaE2!x4nDwWuihqUmkc1d74nQ$ zqpxZ3edT&j=+My&x;tppyr5ANv<3D~CrUcBC6s2QkNiw!w();~XG!0AIm(uDnN9mF z$qxowQD!@z)2_xN2WQ&km%E>YSK#wzDU2~r-J~54%a<(CWUxuMJhW0G*_&|y1XM?RBr%cM9sa`>1X!uKNvP{TCcVe6)0n+y-13qO&d3wVeozX4um5|JEe4FmtDD{QQ{&TR(V&g zS}B`Q_g>i)l?KD&19q;)F&}LlJ6YV|i*3U%n>%-|TSoj3gsoe*Xou2h^GInyoTzAlk|<0eHZmmca$(^O-lF{hgU-Z3 zzOVs6+bOU7FRC^xUx{-_!P^b_KzElYb*!28Xk)4Wn@kjX-+vJuCY9nL+uipD(ZngL0(&k;Ro8Bq%qMd@J&Y>V`RrwGoAaCn%fYtf$X^ zd6Ek4!rMcHNw%82npIdNSD=D>D3xCqbpse33W6U8(P{7y0|$(E`_p$BObyKkVjho* z@pyE^xDrgUEv?vz8BCRhz>6*_zQ_}on`e!V}&UXS70cR9A-4123(CRL<{9cmX==@ zSEG>8tAvl&qeT)0eE`IFmgY2M_z{gawk@a;8aR`79A%87sdwcH^Y^1KK8`BW;d>huPQ2>>6Nq9joH3#CJ^Km=(Lp;4zK} zmGMW894v2>1x2m60)^7Dj>X2Ca7osk)XH*?j{GoL;phUc$REm7#ly#VC(DzB!=-$V z50eQZa=enk$)F}ci>3Hlv|xdSw;zQuW68QYnKneHuWW3G4sg;&5odYmy);3g9VYEH zBL|6FhL6%LquorK93`{MWQ*v7Lw-Cc{iGd55I-%H?ICXZ!&v*OWlOCb)AhqL$3Yzp zT&T+(+7?f4a?ehr^&8iP)2Gka#Q3aicHOwyYsU|*QREilZg}%w-wxNWUk^Y2@eil` z=Ey-Q#Sa{iO{d2m)ug&yp`VLR;<>nWao8gJUksu@`}_;ry|Q#!hbb8T@ZS63$}OQQSFQ*gm(99(GhwIQ zTF3$fy9j8%rsVhbEE!s>9ISQh>Jt|hO}Gh>KQ0lexU0X&uOuF-BT%Tjd?7Zxd^6-zJejZxYhqf+i)h_L!a7r?wS7roS zr0{Q+NdXq7=qr5;22bCVQfyF)1H0W+_#-FrXG{_M?%1#M9{(QBzA~K`QOUO9q0k;g z7Aw0ctOTI8>uuc*MPE>jU#}#3UrwD2bD2|CQ<&NO; zwRiBz!W_pe%z9?BCQto&JaBegfz2wUc}KXIQdhwppAt;?fNKJ?j|5lppAF81KSe0g zr}lEFph=pry7&7~LR?q5>1QNX>@9+`JSmJ?lm@+8PhHyn(p;`t0piatR)%in7 znL`a{wE=?GRtf-pr|r(FydY-?!5AGG8)a4)B~Ks9V~?yd;HZ=+faA_0^DO+}?{E(f z2tfpe9p;mHe4{fGTe=Zu;=(|lCh@cJ9LAFhDaDGZdVYMR`0yQZvbP*q3D;~qc*SBV zfl9c7PbFN5pW^Ce@HBmeAm$Q(V>v8D&A5^-&S{Xv2YL!>VSr&g7FQl_G+iBEp4f$$ zO^Z*Q=Z9C8cA(_&6c$lUXfAvR=gwcrGvZgO=@g%G+^OT3W|rofMOxBm&{2MH)ZoPF zZZp7(?G+qxBYolun|T&~JYAk?IRK}yEUr#-!c@YQFe!gz)2z%NvA(O}lftZce}Zk& z`OoO8t=ShYUzJ^sd0|m=$@njmkL_DFSPLQCMBGvxj~LKO5H@L`yLDvZYnrA z*GVCu$%r^1H|w6ho7!^StCeRNxz=O_e)9AywMi1n=hqTG;0X>qNf$os>Ae{~Jio`3 zVYEonU{b*Vj$LyNjj|&qdSOr>qqzebw4XnJNrroGgtco|E1h~X*vqPzmz!rEpMxWg zJdoyvrWifV-(Rb@yOhs~L3*C|Oq=}j^pnm2bU=&0Yt+$vCW4y$Pq#y1OTIm_^*0rc zT_4~2=Bv6{?vg3NIy;ZaPS2I_=ieQ@gTCixPk8tD@7ZpUAOGlw%09~Msldb2xNzZ; z?bu@CJQ0Vju3f6t;teMGTC3ZZk-wTo=Do0jk8dShwckk zLr~GEL*&yu{mpIBaqYf=aOV6)%VMK!ncYv4;MnbqY`>rGYEMt-(yfNKZVl*o z*<9@kZ8V(e8%N9Yh^f=b;rMc+b4SMSZaZf2$pZ&8F~u z`kANHF1DF1u3!B8^>9{;PbiwVZhcHW)o8hO=Z*B?ARv9QP0cfm)Z9epU;w!ZOWE9z8}`U(&|os@TU zoYDQuVDe-vg)7G=DoRFj@QLxYJFEb+$b}#BBpumdH|ID-5=6vmDMuczC=aDZ8bu#6 z@?B2l@uEVJI^w7wuDpzqMqZBT!Zn+(?V!rVXJRxbeU#VcRLliU4O-A!V7og}cq7xH zxd(9?Ie$3J{Yl4RDP7BHS39nrFBqaYMP|@GaP*-x43uF^}`F=s2#Z3?pp8 zfuF^7kHYhzRDOAfk_zAS-770E955=t!}~L(oBR25DqwkO;1_X)6>zaLjqeUC;p+Z* z&xzuiO)E`@22lQ;;+MWx$2HQt)LEu!dj9zNq*)=&JN3h(QaoUu2k&_TuKlWoN zyIa(+bBO^vA?X*hyZVMk2E&IRer!80UwY}QVZ-_jh6g*%S+K%%49@Yh5B)5bQf!4C zosK>nq0ve>Wc^d={4Xjh{PDC;J4R_499!n?AF!^gDe|)6Kr;edp!j>G?B_=YIZ7 zHK^p1#8-f@_+er{m>H(@$X@$Dd=tDy8H8dFfQ^;@|~)AQyX$9JBe(~7*k4%26hUH)4s9nWVXd|sYIKK|h4d89a|_@wV? z*lhX^n+UGs&0{QFJw1O`!qv;~xchfDo_}-9_Lg=R-3!;OU6uX1{d77UyvdHApa1+H zP1(h+sa74eTEBjsDMPB=!Z;Q9K<75?I-M$q&9%*&Hrg@GsY-LA>A)*$Z6W zAX*R29hS|)zA0CJp#+3SQ4C>M2*)uvj+mlw(q|Tye)Ep=whs?q)KS6vq5L}Db;cB53v_&tKF)2nI*lT( zvCs7KxomO#{hMN$p91<0HzsuK#;&IP8W`-C-Mj)1MLO2&hUV3)S6iELnReo|7JhWAa*K9^P=>TT91m-gq3l%g1ut;%3~5py zI4_rdBtKr4*(X7=e*T?AFZAJ2Nr=DalZNG85W!;1EUXjuuAE;zsK=(QvN_z4r|vF&M&dS?_s4mWy4YC3zx5Gm+2*q zhX-|owd{)OHdV?Ee?l{-TlQ%QWPUu1d#B&Lr!>#PO6`i+rM9J4bA;!g+0@gvuUTqG z?EGRZKcY5NSGXjAvJr+IjHVP53`g9odnlD(PFTBwS;E-2O*?^ka*T|vqv=g`9uF8o zixnJ%xeI?2W{SgBRNuDj1O>()2K&-2;lNWE>81F1`te4fa+t>j9~g%tJMQPts<$e=H$-+l%tLqTjoYk&y$WdXq)+DX>LT*4|%0DcYmiT@I0D3 zEh^ERcr$Hsd~MR}7~1K7Tv^tx0u0UW`r<&?x&2YC+Dy(Ew%6~hyuHFJDZf_Z z9nz=#d2JH<@OOIzo>dysy;tgv;E(N~D4#OLfIFIi;=tdZ)#OJCvj~MB z;?K0nDC@JllhRd`p1yuke1W5$dvElI9@)F$Ce!J3E0!s`+^%2?a#JMa$nS}C- zn`xV;K!*49UJqaF-WyKa?R|4CAL_QDaQVWDmCM6vDQsSS^<^D(sm-3$o`XljwVoTs z^Bj+X_hTW{4mA0wB+tE^$g}Balk7~Q|3Km7M_wXg_vZJ4jQ^jzct!TH7TOpY>F)LF z7*vzlgaOW9I+lXI_(5iFQ@o~rW^KHn(UUEE?%ut}zOjE+$qj0UCp-5R%hp(Qu?{)f z+$a8f>7_q2+g)$G@vmlM@a0!t4*lvA8LPRe0^)%eV}f2?F4LifvblA0)z6KD(`PTn zesvxfL`5V2bi9PGtzSnDR35*g1hjfqeS;5ngZi~_<<7?u{!PC3y04@ia3qX5CGDMh zG$lg;7nFu}BcF{-q#P3+!4X^uM_hK9^N+C-{^s=LA_SB&#p7y)f)b=O){b?GpV`tB zjj}MO56=<7W4kQP{TvRA^2GTTZ9MWLaNcRtz~Ir;G5#vfDKkLFmAbOyYKmAZu9P2o zx&i+*&uX})Fwh}CN6T^bGIGl!j`=WUEVaoJT|JE~U281|_)xENl}Fa4xO)8+ah)cb z4@vnotVQ5i;#YQ?s$p3l1&&c}PoCy!Ia8W@*&GfH$d0*T7Ov9o{<85acrT4aYsV}!s+n={Ui54ci!MHskRrA9x; z6*%u64}371ilD@S*W3c022)s=z+p@X`NKtABg}A?J)sh=NjYF5h4(y5jiS69_~Rn& zc!&NanrCsPyck8q-*HW84xZK#2yPuiS`MX792`4O{0zF$T*&&iM;eR6CQ5UPHHzjL z{-{p#eEu-Jz%_?IsK-2-Tj#H%HqZve7lVZ&pM$8h;gh9#${)}Z2R>E#yo}~iu|vE( znnzxauoPFqN7zi8gcg^ayO)~#Nl8|QR(Un|g)b;}F4W?j2^ z(^iBy=E9AMT$N3mY?k7cjs>H<47eEpXIKJ1-?3a(u(X^Amzrwh0T(sTGS9NkZx;ME-iGfcQk3}4;QrafI+#*Tjhzu z5XIOr86RGuBSn5x$Yfn2vulxqGi@^Vq40h!`~feHlGzE(r=p)^XU0g~h$(=lTluv} zlWXrAv+Zmuz8~AN#gf^xcc1ZlOcO4Tee6`^k(Y*srA9x$xFs*lMEp!iUl<=uB>q&! zS)s)QcJ7^&!s!-PN!PoljW4 z99wH$lv$im)qec(r{P=Q`i5$lkw#_LH_&hLl$!@x^gw0>^*b9QbJN}5{Kp@M|MWNiA^ha;{yrS<>W-MQx2HBz zgxT0WrU?v%gN0H;Ha-Gtfx)K?rg$hKJuLJt?v#>$#3#n9Rt_%yD8rR>E0rUKRl`+j zx^fJ>QJA63@p6ExSU2*rU_LjDG>?m&l#4N~)0J=N?K_C5TZc`Q=8jL6t|_irSUJs^ zQ;y~j@QL-|uo8bzjy#$}oTyY{PD#8tr?j?Xh+52Y99A55jS%Lu)qlm|Wo;!1oPR|?D0oX$&JtIi^i<`P`P zQL%Yjs}DGvjL_jJPp_jW+$!N3D`YI1Q=gGPN;J>nN?oy(0HAxZF-o7}rQOcvqGmS^mhEgV{F8V69)1Gz^eq_XOn? ziYnv_VHteVISy(Sy-Pd2;C;JUPTAejF0UK?L!q_3!;Wp7lYwe>V-Vg~nz^-Y=<+qu zw=s;&mW+|?F~yk5!f{D%<>K}~y+S>mRAI#ivSvKKl6M z(A9N1eDAgI>PT9pTS1}8tnlcgo5HVu{jcgbZfYT;ba9F&KR7%ne6HJZNfZoC^BO|E z`V_`Ww7IhWzCh=(#!;kA-02v*GG^(~F3fx3=u37VIARMw3si6LF71;ER%uR9ZS1P? zAmePgxNse@&W>N{xF9XZkY>pS4~mRR?wO~b3J3NdtOPdy0U5iet-ba3JG$(pMMt*# zWS{Gr?Cos`U;p}7!xvxd4gcfsej5JM|MWNEM?d~S_`9F{y$tWShxVn*)MuWLlYf<+ z@d>-8=>vPT`|G;?SoFb$9b-@wUeL(;H5DM8-}soYTyDoXL%Il@&I{7Ma!~d>=hpjp zf3B2)?cthi*Y!y824CCQqBy^~cjH&2m-kKd>$6o=l!5wX4;N!~6kkYG#_TN`H~H9t zu?w;ag(7nZ=oXdZ;-RFhfW=*B z%wedHI9?(w`0y9w6%deZJhjL87EG2$U&MZ&A}(d zmAZ;Lhdf-FQ|9o8%4NJ$1I?WW;1Av-e>hzu@Az)o$b+JvaPH*4{J19jna{+jaGEo1F=kwe{sr-VOd}5C<4%*p7BZj?G7>$NzmBJvD z4+IhB2r`5l@oZ95ASAG;94atNp#y}-rZf=ot>VZ&fsr;z03&9KPsCLUmr=OVWaN|% z4O}8K#!GNTcp9z>HZEM#a%6C|a%h63zL!;KCgl1KFLb?oQ|i+=VS1P38@5Estw*L$CVXL5}Ij~MY>YAiHxX) z=I{W59ouh>+7UP`!}HfP8123wBi6FNu}Sv8mbF!y2pKz#`NPDgn(I7%BK+I${}6UO zvE6LQuxd7>;|Lhued+683ukpK1fHTJ2VeLw<>l)9kuL|cZIZ#&(10!iIC(~|w1c~$ zQFx=os*~c5)o9x39NlU&G&08&=kTA&-7q&S6Ru1=`v*qs)|?IAD27Oz}q+j z#ABzpJ!?pLu+>_(dui7ld>#i*vAozz+WG7=HmG4RlWhYtZSr39lX389lMV3!jyj!q zKS_FVkjVuK3pMGRZU;|ci)VObNE3wVxz&z-g?0kp-zzsHrLvDxrZP|3)tANX-M2TK z(ye(zQa)^a?6G*%$>d;^Nysad2hEb<*jZxL8rxMzJCBC$bKSD>*eIp_fXPrM$n4%B zEbMdz<1`^1W2py^GSnuR-lylwY)gNd#;%Bb_=sDDr()-GN{jTJU2w;{&S@u{jyg9l zunP;IK{{6Q@oCkuYeA9a6Y9M2E5jrBnDmAvXZp0eDJ)H~DZO(^!4pqB9zOnPS6K2F z9pa(UefD+TwtQJe@1K%gu&=!ELg?-54Oey9!g3v{My5RT^wYL8@t&g^MNidW{_khL2g3u7Yc z(d)y;ZJPgjyqa-M%OM0tm4mzrxI#1X!Hq5l$|(3L?nr{LqstNLem4UHS1*UtmAJUP za!?<}hN`LQ(nv*VLBAn4keZS?Y z?-K7AxWFG--l?7D?99dG(cEBT@CTJb{o(RxK94?1CtesM&C(nfz8bkBStQz`+>7!^ zmCE&y8TU{szgT6!8S{vEY6j80mFP

-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

MqJM%B9TqsPQ2PZ_WPk(V7f4l-zMqUs2^ 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 you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/elastic/kibana). Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Patryk Kopyciński --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 292f997c62325..4f4ce4cdf4c63 100644 --- a/package.json +++ b/package.json @@ -1328,7 +1328,7 @@ "cypress-pipe": "^2.0.0", "cypress-react-selector": "^3.0.0", "cypress-real-events": "^1.7.6", - "cypress-recurse": "^1.26.0", + "cypress-recurse": "^1.27.0", "date-fns": "^2.29.3", "debug": "^2.6.9", "delete-empty": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index 35770d9854e55..9be0124443384 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12947,10 +12947,10 @@ cypress-real-events@^1.7.6: resolved "https://registry.yarnpkg.com/cypress-real-events/-/cypress-real-events-1.7.6.tgz#6f17e0b2ceea1d6dc60f6737d8f84cc517bbbb4c" integrity sha512-yP6GnRrbm6HK5q4DH6Nnupz37nOfZu/xn1xFYqsE2o4G73giPWQOdu6375QYpwfU1cvHNCgyD2bQ2hPH9D7NMw== -cypress-recurse@^1.26.0: - version "1.26.0" - resolved "https://registry.yarnpkg.com/cypress-recurse/-/cypress-recurse-1.26.0.tgz#e897b8c849af25214ce8785c57479a7fd98d20a5" - integrity sha512-FioASB4kPgO8G0l4SkjPyFnm2VMvfG0zbjr3N/FqOiiq+YRtsXqGvFIYK9jKay90Ciqq3hKVLTuMCaNpniXYfA== +cypress-recurse@^1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/cypress-recurse/-/cypress-recurse-1.27.0.tgz#0c61e809c5f7740a7e907714614c49c72dcb5c1f" + integrity sha512-BCD83UqaxlD+JiqZn1PvIhHRXasgfCt57vLC1Fcyifvxh4QklELRcYUJV3MdhKamMkmajaErLfnCNbZ8VJ5SIg== dependencies: humanize-duration "^3.27.3" From 49b3c1dd1227d46f479a8b0bd701fdfc46e6e5cf Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 13 Feb 2023 00:54:03 -0500 Subject: [PATCH 115/203] [api-docs] 2023-02-13 Daily api_docs build (#150970) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/247 --- 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_chat.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.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/ecs_data_quality_dashboard.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/files_management.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.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_alerts_ui_shared.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_analytics_shippers_gainsight.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.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_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mocks.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_content_management_content_editor.mdx | 2 +- api_docs/kbn_content_management_table_list.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_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.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_custom_branding_browser.mdx | 2 +- api_docs/kbn_core_custom_branding_browser_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- api_docs/kbn_core_custom_branding_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_server_mocks.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_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- api_docs/kbn_core_http_resources_server_internal.mdx | 2 +- api_docs/kbn_core_http_resources_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_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_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.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_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_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_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.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_test_helpers_kbn_server.mdx | 2 +- api_docs/kbn_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.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_ui_settings_server.mdx | 2 +- api_docs/kbn_core_ui_settings_server_internal.mdx | 2 +- api_docs/kbn_core_ui_settings_server_mocks.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_cypress_config.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_ecs.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_es.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_es_types.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_ftr_common_functional_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.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_i18n_react.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_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- api_docs/kbn_language_documentation_popover.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_date_picker.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_url_state.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_osquery_io_ts_types.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_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- api_docs/kbn_securitysolution_exception_list_components.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_avatar_solution.mdx | 2 +- api_docs/kbn_shared_ux_avatar_user_profile_components.mdx | 2 +- api_docs/kbn_shared_ux_button_exit_full_screen.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_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_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_prompt_not_found.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_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.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_test_subj_selector.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.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/notifications.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/profiling.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/stack_connectors.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_histogram.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 +- 476 files changed, 476 insertions(+), 476 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 813c55a3dd2a2..b9be91ce21ae0 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: 2023-02-12 +date: 2023-02-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 b39f6f397bd9e..2aad7fea352bd 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: 2023-02-12 +date: 2023-02-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 938dd5b18731f..5709065f00cef 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: 2023-02-12 +date: 2023-02-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 5e3e3868c5a9c..375da7aabf00c 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: 2023-02-12 +date: 2023-02-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 852cf61472cff..2274cfb6f7581 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: 2023-02-12 +date: 2023-02-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 69dadf4864adc..573a7276b9699 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: 2023-02-12 +date: 2023-02-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 58d1cdc68e407..ae8d802eb9bb1 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: 2023-02-12 +date: 2023-02-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 dbf67ddb22198..d3c44ad29fbe3 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: 2023-02-12 +date: 2023-02-13 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 2216bc925b32d..b57d875ca98ff 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: 2023-02-12 +date: 2023-02-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 428c96e50aede..208035ee0e511 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: 2023-02-12 +date: 2023-02-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 556d70073f7d2..3dd05b4caa69b 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index 01ae66e6497a4..8348bc64b0c57 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index 7ed001d3ed649..e59aaa8f4662b 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index c2de3837cab51..4d1771e9abed3 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index e1f4e12344cfa..c9ba0c13625b9 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 48c3176b0caa0..1f26d30425d20 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: 2023-02-12 +date: 2023-02-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 f08adab881d81..1e72619a9d2d3 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index b8f0fd00afd3c..4d2b9e6e5351d 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index cf35c129be7cc..71cd2e5f65cd4 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 3f562d66d1d95..8bdd11f8b69b1 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: 2023-02-12 +date: 2023-02-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 79dedee4c7207..6e387484de43f 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: 2023-02-12 +date: 2023-02-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 44b0266b0aa90..09a6d90b76b84 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: 2023-02-12 +date: 2023-02-13 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 be0a2662972f9..190d0276f2e2d 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: 2023-02-12 +date: 2023-02-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 d8af7106929ff..ab079f19bf2d2 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: 2023-02-12 +date: 2023-02-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 24a012375a333..bbb7a415a99e1 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: 2023-02-12 +date: 2023-02-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 711edc567186c..cf8efde83624e 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: 2023-02-12 +date: 2023-02-13 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 de536feedf6f4..6e12552b4a433 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: 2023-02-12 +date: 2023-02-13 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 44f3b35c1c8ff..c4a0c8822f005 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: 2023-02-12 +date: 2023-02-13 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 1fe604520ce6a..e6492a967fb77 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: 2023-02-12 +date: 2023-02-13 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 d38796736b0a3..8381a91277964 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: 2023-02-12 +date: 2023-02-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 61cc6e3587369..37268da64d6fa 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index c1a7fcf35f2db..4bcdb9a901e1f 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 95dc3e34030ab..50f8afa08c804 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index d873e628ca533..41d539f12123a 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: 2023-02-12 +date: 2023-02-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 e56057f309d7a..7ae9672c44932 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: 2023-02-12 +date: 2023-02-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 aae18a7bdaabf..10b4c487e8fd6 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index ef5f53b081cc2..8ab9a88d3a593 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index b2df9239b85aa..a42c12b9cf58d 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: 2023-02-12 +date: 2023-02-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 18af46a0e1631..28e675627e8ef 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: 2023-02-12 +date: 2023-02-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 cd323f5004211..1b99d881f3521 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: 2023-02-12 +date: 2023-02-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 20702e001aab2..0415fed328382 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: 2023-02-12 +date: 2023-02-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 919cbf6be03ab..434c2bd5ea789 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: 2023-02-12 +date: 2023-02-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 b98e9e1a65600..b7b0b6b76eb4f 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: 2023-02-12 +date: 2023-02-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 41cb5a09e511a..166b99f16fcab 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: 2023-02-12 +date: 2023-02-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 fcb017ed69e93..06e9cec3bc982 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: 2023-02-12 +date: 2023-02-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 de26338af4a6a..c8d1013f8c1de 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: 2023-02-12 +date: 2023-02-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 103a70fe05db4..cd9983cefeb37 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: 2023-02-12 +date: 2023-02-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 8b367f07072f1..6602fc473f8b1 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: 2023-02-12 +date: 2023-02-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 f91eb83800e9d..4d812d11b4bfc 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: 2023-02-12 +date: 2023-02-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 3122f9a07b962..a8ba54652620f 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: 2023-02-12 +date: 2023-02-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 14fbb52a69f6f..7fd4da9966fd9 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: 2023-02-12 +date: 2023-02-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 76714dc9f3e94..64c80e93089f1 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: 2023-02-12 +date: 2023-02-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 1f7b579d80424..7a6ad29dfc08e 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: 2023-02-12 +date: 2023-02-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 647729e8da615..51d9a7b54a37c 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: 2023-02-12 +date: 2023-02-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 b1c9627d09248..ad67465521184 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: 2023-02-12 +date: 2023-02-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 f7d36f880c5d4..af19b56f0b273 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: 2023-02-12 +date: 2023-02-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 c273986c4a27a..122fce6eb9c20 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: 2023-02-12 +date: 2023-02-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 bc787210ceb73..fdf04289d9dc1 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: 2023-02-12 +date: 2023-02-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 7c050d8b801f5..c7cf28c806c03 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: 2023-02-12 +date: 2023-02-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 4b2b0a870d3da..ec7a134ceda16 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: 2023-02-12 +date: 2023-02-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 e2ac33332a484..57c4d6a70bdb4 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: 2023-02-12 +date: 2023-02-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 1ec5a68993b27..14ccd3730ff42 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 1f2681d60f609..792cafaeee9b5 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index d3f8a48d9a787..a1e6bfd8c7afc 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: 2023-02-12 +date: 2023-02-13 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 2a274a4c9c47f..905c4673901c1 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index 878f73ada9182..ad0f929239339 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 1ad0ef6172fb9..6284487517edb 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 363cb25758c54..5749a8873dffb 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index d94f9ad1b8202..1152691ad7e2a 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: 2023-02-12 +date: 2023-02-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 8ff3da30e5a89..e719e5935fa94 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: 2023-02-12 +date: 2023-02-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 7b1bb50234db7..5ee14e5b98344 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: 2023-02-12 +date: 2023-02-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 729ec6188f2ac..a7a08e977cbee 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: 2023-02-12 +date: 2023-02-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 d21627aa81e66..991447d3f14bf 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: 2023-02-12 +date: 2023-02-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 dc5a80225254c..64a742a86b13e 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: 2023-02-12 +date: 2023-02-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 ca552ff8d1629..76e6fdd21d06a 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: 2023-02-12 +date: 2023-02-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 6f59bf57897ad..3d416f3e7adad 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: 2023-02-12 +date: 2023-02-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 1a1908b7633cd..d16cee6987121 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index f91a0e29fc3e2..f4e37973e7945 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 642b3dd629a8e..45f1e8636073c 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: 2023-02-12 +date: 2023-02-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 07771bc4163d9..17ce8a3a75c3a 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: 2023-02-12 +date: 2023-02-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 23fa91267d747..026ca948a937c 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: 2023-02-12 +date: 2023-02-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 855afa8469bfd..a2c5c4aed4090 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: 2023-02-12 +date: 2023-02-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 adf17dfbf355f..f97c7500ae697 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: 2023-02-12 +date: 2023-02-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 d753cfb676642..c6a5d84adf8fa 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: 2023-02-12 +date: 2023-02-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_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index d8a5d93121943..88c4a26d520e1 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 78ebf5dc9ad3b..cf5438c67ca4c 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: 2023-02-12 +date: 2023-02-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 1022ac0513a70..291ddaf5f2b86 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index bff65a26736e1..02cabdd7fc373 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 8c870118ed7ee..ea0f36189cff5 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: 2023-02-12 +date: 2023-02-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 c09f534279dc7..c26f6d441476b 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index a01cabc966cda..e1f07f443dc33 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 761fb05713d1d..51582d43a448a 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index b3fca47a7a6b4..1702efaaa3cc0 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 0dd0961f0988f..ed0c1570a7a62 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: 2023-02-12 +date: 2023-02-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 6592096927c92..31464a88598e1 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: 2023-02-12 +date: 2023-02-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 e7b2d6b442779..1ead9fc172d5c 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: 2023-02-12 +date: 2023-02-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 120c5af78fcfc..d5e2460a36e5f 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: 2023-02-12 +date: 2023-02-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 aa766b0ef9bc1..f81eb5b015106 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: 2023-02-12 +date: 2023-02-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_code_editor.mdx b/api_docs/kbn_code_editor.mdx index 6445fa1670bc5..49fcd04616f61 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mocks.mdx b/api_docs/kbn_code_editor_mocks.mdx index 8c14fd72a6283..6cc31f555196f 100644 --- a/api_docs/kbn_code_editor_mocks.mdx +++ b/api_docs/kbn_code_editor_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mocks title: "@kbn/code-editor-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 472ae27aee77b..456df6361506d 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: 2023-02-12 +date: 2023-02-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 d790fe133403e..cd9e09fb2a3b9 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: 2023-02-12 +date: 2023-02-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 16c51e918c159..4aa975df02e1e 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: 2023-02-12 +date: 2023-02-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 4c97f7de5e320..c668492d6241f 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 21147dd02ac25..d9be82f46386f 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index 9f0182f5662bf..afdcd894c491e 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 740e3444912e4..591a368e29051 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: 2023-02-12 +date: 2023-02-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 1a26b065b6a0d..14deacecb4c32 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: 2023-02-12 +date: 2023-02-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 73afabdb918f2..62b8135649c4e 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: 2023-02-12 +date: 2023-02-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 595cee1792bf1..1b1edb3251960 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: 2023-02-12 +date: 2023-02-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 a73bbabf7e769..e340db4e7f5bb 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: 2023-02-12 +date: 2023-02-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 66d31c6463d42..1be403c6b4597 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: 2023-02-12 +date: 2023-02-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 05de1595f2c1a..f83439d5eb902 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: 2023-02-12 +date: 2023-02-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 d5be206de547a..1dfbf14f847cf 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: 2023-02-12 +date: 2023-02-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 519b2b47b9611..1cde78fae358a 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: 2023-02-12 +date: 2023-02-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 e31a239ceba7f..53b4331aa5e18 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: 2023-02-12 +date: 2023-02-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_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index a2626fe7d22f4..ddcab0894c486 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index 8f857ae2e250e..c135a057c97bc 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 67d4c8200c4a4..0dc95b9f29d11 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 5c379876ff9a3..487d2796b3453 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: 2023-02-12 +date: 2023-02-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 d8ed0609b1704..02b331420427f 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: 2023-02-12 +date: 2023-02-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 f6cba0df640e9..9b6f503f6bb42 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: 2023-02-12 +date: 2023-02-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 71d11b80843f7..ef74a650c5f19 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: 2023-02-12 +date: 2023-02-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 d9d1bda5615d1..9ce3a7cc45195 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: 2023-02-12 +date: 2023-02-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 9a8e8491b96a3..4355357f1a0cb 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: 2023-02-12 +date: 2023-02-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 b982bf2b010fc..cfb6264ba1107 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: 2023-02-12 +date: 2023-02-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 18fd7705dd0c2..4212631ed672a 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: 2023-02-12 +date: 2023-02-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 66eb4e51b49ee..401d6435d6882 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: 2023-02-12 +date: 2023-02-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 44abe9a764fa5..f1cd7b3907cd9 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: 2023-02-12 +date: 2023-02-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 7ce2e27362f45..ced5e9431d344 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: 2023-02-12 +date: 2023-02-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_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 08d8f97df7ddb..3aa260c5a1727 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index 87f7574bc0fa3..899144dfc8a5f 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 62262edf3581e..2ac6be9f87d41 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 0a136b68d61ad..33b8c42f4f4f3 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 8255a607c241d..1048717f2c677 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 134a5f80c79b8..efbbfb42370d2 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index 8e0b9bb47b23c..9e0057d919719 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index bd6c91333edef..0e74a2626206c 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: 2023-02-12 +date: 2023-02-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 3a5c3cb864ccf..5142aa3a507ac 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: 2023-02-12 +date: 2023-02-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 64fc4a8f8f9d8..c93c1d05ecf81 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: 2023-02-12 +date: 2023-02-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 173d319ca3864..19d2fed2812e5 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: 2023-02-12 +date: 2023-02-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 f6c470997692c..711cca96375e0 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: 2023-02-12 +date: 2023-02-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 20d4e48c5522c..3782a3a2f2ab7 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: 2023-02-12 +date: 2023-02-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 ea8151e76e320..106bea0abaddf 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: 2023-02-12 +date: 2023-02-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 7630af8fb2940..db14485f7a21a 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: 2023-02-12 +date: 2023-02-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 5e0cceea5dfda..5071631cf2f17 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: 2023-02-12 +date: 2023-02-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 a271b2c6b25f8..9fb36df949fe4 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: 2023-02-12 +date: 2023-02-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 37ebba13decd9..d91c8ef6fbcc9 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: 2023-02-12 +date: 2023-02-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 835667e52ba0a..5a81a0ed08442 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: 2023-02-12 +date: 2023-02-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 d3486c4f64042..2370318830682 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: 2023-02-12 +date: 2023-02-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 ce5fea18b157d..83a609cb286b1 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: 2023-02-12 +date: 2023-02-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 a59f4f409468e..8285d654c2457 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: 2023-02-12 +date: 2023-02-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 15a1ee74669f4..cbc198117529b 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: 2023-02-12 +date: 2023-02-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 4d82d04b4566d..ac8510ebf64a3 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: 2023-02-12 +date: 2023-02-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 999585bf8710b..b0dc8036d406e 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: 2023-02-12 +date: 2023-02-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 90b5700a246cb..28974492f3fc4 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: 2023-02-12 +date: 2023-02-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 059a5be172710..c0eb0111c76ca 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: 2023-02-12 +date: 2023-02-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 e0dffaba9c365..08e5734096897 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: 2023-02-12 +date: 2023-02-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 9392d295b5ac6..a0e10bcdeaf96 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: 2023-02-12 +date: 2023-02-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 3a0b2f7081dca..b098042680c50 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: 2023-02-12 +date: 2023-02-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 372e13afdac9c..122d14760368f 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: 2023-02-12 +date: 2023-02-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 20e5da587d057..a748755f6713d 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: 2023-02-12 +date: 2023-02-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 5d577bff301da..7bbc2f221deaa 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: 2023-02-12 +date: 2023-02-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 0122789fa6ced..74c01aa514e21 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: 2023-02-12 +date: 2023-02-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 9fe6ae28240ac..28f7097f8ad73 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: 2023-02-12 +date: 2023-02-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 3e7469b5d8657..687b92558e613 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: 2023-02-12 +date: 2023-02-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 be8ea6ecadd7e..b2135ed5b6219 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: 2023-02-12 +date: 2023-02-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 6e59ab64cf85c..000deefbf8e0b 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: 2023-02-12 +date: 2023-02-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 75f31f757ae7e..455bb6d024f93 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: 2023-02-12 +date: 2023-02-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_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 62c3679d4d83a..5648e9c6de077 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index e5ef7d056b968..2d999eda8f05f 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index e4d99d86e5fae..b27c32bdd02c8 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 169e161811097..701f651dc888b 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_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 73c7a428ef079..a51d636f675d2 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: 2023-02-12 +date: 2023-02-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 271ef6376745f..961663af494d8 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: 2023-02-12 +date: 2023-02-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 d13a6a4f31a99..00bc4e7585949 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: 2023-02-12 +date: 2023-02-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 b2d034f422a27..1a0a96d63c7b1 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: 2023-02-12 +date: 2023-02-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 f67f859278958..cc704b8f02f84 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: 2023-02-12 +date: 2023-02-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 ce010875bd4c9..61bce5767465d 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: 2023-02-12 +date: 2023-02-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 b5789f1963c10..daf3cefc4df6e 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: 2023-02-12 +date: 2023-02-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 207cdc7de8b7f..446f3a0574c61 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: 2023-02-12 +date: 2023-02-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 164d865679147..b733326b6280d 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: 2023-02-12 +date: 2023-02-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 49c24e74673ca..55f063983fb98 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: 2023-02-12 +date: 2023-02-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_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 4f54f3307c67e..2638692eb440b 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: 2023-02-12 +date: 2023-02-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 fc57707852a1c..73960cf9d8992 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: 2023-02-12 +date: 2023-02-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 f610868746634..2a67cbc81cb59 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: 2023-02-12 +date: 2023-02-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_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index aa18a31e93ba5..558fa7aad1707 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index a2d86a12ac50c..0b76f6e30963e 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index eca7da5b6b742..4c9eb53377958 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index a42a69a0f0fa6..2080026784a37 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 7872e1fb7352c..463b730063e3e 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 990ebf5cadcb3..28486fecbb7a2 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 09b5cda10db89..1f6587b96ba29 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: 2023-02-12 +date: 2023-02-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 020150e66159e..f4c9c22ca1194 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: 2023-02-12 +date: 2023-02-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 368ae632ac1ad..41ca1172ecabe 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: 2023-02-12 +date: 2023-02-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 dd7253101be5e..b0470f4d21d82 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: 2023-02-12 +date: 2023-02-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 ac1e24aa269f7..e610ff8c17fdd 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: 2023-02-12 +date: 2023-02-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 39ee87be1f804..1c7fbbdb11e18 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: 2023-02-12 +date: 2023-02-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 2ed3da36f66df..e306b1e55b3c9 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: 2023-02-12 +date: 2023-02-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 20d80fcb6f272..0c28f0ae37ff2 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: 2023-02-12 +date: 2023-02-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 8de8f290304e9..31baac187b00c 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: 2023-02-12 +date: 2023-02-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 3c24fd9f34f35..941d30019470a 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: 2023-02-12 +date: 2023-02-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 e281dbf22979d..90b1aa8fceb02 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: 2023-02-12 +date: 2023-02-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 86b711260a348..12dbd00dabdbf 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: 2023-02-12 +date: 2023-02-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 e9345895344bd..af87e4732a5ca 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: 2023-02-12 +date: 2023-02-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 e19e1a736663c..7908493e3bd84 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: 2023-02-12 +date: 2023-02-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 0322032628edd..23d5e24a71dbd 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: 2023-02-12 +date: 2023-02-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 5cd885e5b7c35..49841dce2cf5b 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: 2023-02-12 +date: 2023-02-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 a7d1282d6c179..5a80429b2c356 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: 2023-02-12 +date: 2023-02-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 9e520413b4648..c12d0ceb9e475 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: 2023-02-12 +date: 2023-02-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_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 5a51258efa5d9..8df2e2c56f68b 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 196ecb3da0a4c..5cbd47140e5f9 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 6ea4f7a196a9a..dc1412daabfa3 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index ce06d927091b9..96a2824bb4c10 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 56abe728ebcc1..b296c61e4b55d 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: 2023-02-12 +date: 2023-02-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 0b2f4fd48f1d3..21887f2b0ce00 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: 2023-02-12 +date: 2023-02-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 8f49d78e9f9e3..6d290cc27d103 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: 2023-02-12 +date: 2023-02-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_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index 787fe669c3302..598972fe50f57 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index 03ca4ce003d02..631dcb4e6a58c 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index 353d96d4904a9..f1855def884c1 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.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 87286bfb27308..38d0fa2530610 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: 2023-02-12 +date: 2023-02-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 0d1e6f6a26ce6..dccc1db9033f5 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: 2023-02-12 +date: 2023-02-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 2100187d0126a..6cb17b31aa71a 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: 2023-02-12 +date: 2023-02-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 63f1b415fefa0..6682dbccbc9a4 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: 2023-02-12 +date: 2023-02-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 b524126190a90..b18ebe9715ad5 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: 2023-02-12 +date: 2023-02-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 ae4583f5cfbe7..813c7a72804d4 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: 2023-02-12 +date: 2023-02-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 af445df7751f5..37d9a323ef48c 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: 2023-02-12 +date: 2023-02-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 f5884e9140bdf..9fbf5c4e2f0b5 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: 2023-02-12 +date: 2023-02-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 5926253e06641..d516398c4e614 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: 2023-02-12 +date: 2023-02-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 3821d753f0f82..aa5a5c71f6f07 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: 2023-02-12 +date: 2023-02-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 85e857c92e89e..fce451a8ed782 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: 2023-02-12 +date: 2023-02-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 e8d47d44761ee..2709a7ec38121 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: 2023-02-12 +date: 2023-02-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 d3e7ebd0cc5ba..31c26875fac90 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: 2023-02-12 +date: 2023-02-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 a75bf66fe7dd5..5c5b2138835a0 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: 2023-02-12 +date: 2023-02-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 44cfc318a9165..fc19e8a2c3c78 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: 2023-02-12 +date: 2023-02-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 e7782c3c602fd..fa39dd6643992 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: 2023-02-12 +date: 2023-02-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 581b3425aed30..c9da4e7dbeef7 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: 2023-02-12 +date: 2023-02-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 db62f1d537319..91a54063e7292 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: 2023-02-12 +date: 2023-02-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 422fbfe01ef2e..56270b61a9e2c 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: 2023-02-12 +date: 2023-02-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 7c19ee10bb6af..20c7da9de04af 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: 2023-02-12 +date: 2023-02-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 3142a7d8a4458..705cbac300b07 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: 2023-02-12 +date: 2023-02-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 3b35105b0f724..935b60790e65a 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: 2023-02-12 +date: 2023-02-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 814036da7d525..37a8075002b5e 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: 2023-02-12 +date: 2023-02-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 c1cdf9f113cc7..8b6361fc33338 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: 2023-02-12 +date: 2023-02-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 f75b92c170027..bfedd0af8d072 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: 2023-02-12 +date: 2023-02-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_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 1cc49cbad383b..cbc60f3076e47 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 0b2b0618de14e..735f7a9f60434 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index ac465da312f39..8300daab11e48 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index ab51283a9368d..7b5e1a1395bd6 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: 2023-02-12 +date: 2023-02-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 3a9fc357f3fbc..254ae7ef1a96f 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: 2023-02-12 +date: 2023-02-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 5bfc9f6a34edd..d2da431f68428 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: 2023-02-12 +date: 2023-02-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 8b8c61f7ede60..7c10ceda5424b 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: 2023-02-12 +date: 2023-02-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 9cf809498c642..161c5c13714d1 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: 2023-02-12 +date: 2023-02-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 942265140de03..b31db09714554 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: 2023-02-12 +date: 2023-02-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 d3418d41d1692..1c795f112bab9 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: 2023-02-12 +date: 2023-02-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_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index 477c1496e133f..ac8d45fdceffe 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 488ad0eae5ca4..6e046c1344dba 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 22c13241943dd..74ead129e1195 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 491ee663fc120..f9babf1a55f6b 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: 2023-02-12 +date: 2023-02-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 42113e2ef4a22..b2b85f7e37c4b 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: 2023-02-12 +date: 2023-02-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 7a4164e43a1d4..2521b52ce0234 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: 2023-02-12 +date: 2023-02-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 f2679db2d2efc..22ee9b40be60b 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: 2023-02-12 +date: 2023-02-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 e847a914f27f1..aa77c11009b29 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 4ef861c212399..934dffcadb993 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 787c6a354575c..728c88086d492 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: 2023-02-12 +date: 2023-02-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 ee57c6ad7106c..543f5ef5b784b 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: 2023-02-12 +date: 2023-02-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 2eb6fa6b8212f..39b4f92825652 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: 2023-02-12 +date: 2023-02-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 549ca9ec4ef93..9510ef82c0c45 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: 2023-02-12 +date: 2023-02-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 0e38206f856a2..7afa474345101 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: 2023-02-12 +date: 2023-02-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 ad985d6efcfde..e472fd409f0b5 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: 2023-02-12 +date: 2023-02-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 5ea9e7903321e..e9e0730b6be1a 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: 2023-02-12 +date: 2023-02-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 6b16e1150d7c5..35c1c22510ec6 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index fe68d22a718d9..041a6dcdb99c6 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index e61b630841096..0e2c2acfe927b 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 4d0569ee7f138..64f78fe84dfa8 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index e1134d4498484..631ce9e67ddef 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: 2023-02-12 +date: 2023-02-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 47043dbe633d7..673dd37f2986f 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: 2023-02-12 +date: 2023-02-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 e15e840f330ee..f5c2b2af98557 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 770a2b3ec3167..77f31266d9baa 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 2f973b8cc7f1f..6a0fa8bfe3ddf 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: 2023-02-12 +date: 2023-02-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 f119eb81af445..f5acaf43819ae 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: 2023-02-12 +date: 2023-02-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 81c02472c4083..2ee7b663a20c0 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: 2023-02-12 +date: 2023-02-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_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index eb9ffbe5c94b3..604213f9ab2f5 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 305977304db84..049ba94a844b7 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 5cbb6c3b48407..cd8b4ca92de8b 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index f2c2f772e5f3f..405495dbada19 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: 2023-02-12 +date: 2023-02-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 b6b0f3ff20ec5..bffa6c92c7acf 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 34d80ad7766b4..31bbcdae249f0 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 73dac03610f59..0b30a75c841ad 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: 2023-02-12 +date: 2023-02-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 cf1ab22854cfa..9e33307751194 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: 2023-02-12 +date: 2023-02-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 67e6363217283..a19d44cd81070 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 13773a130b01c..dd8ca1c9fbdb0 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index fcefa294af044..e2f3eb6b2d8a4 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: 2023-02-12 +date: 2023-02-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 2c2cc60b7da3a..9963f1ffc19fb 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: 2023-02-12 +date: 2023-02-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 5e1dfbdaf8e2b..51df3e0d42372 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: 2023-02-12 +date: 2023-02-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 76565d9d77874..92893a4cd7cc1 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 7523307fcbac0..5de3a5f9fe63a 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 13688e3c4c7b4..6adb002bba48b 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index c1cdb27c789f7..3f34de19742c8 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: 2023-02-12 +date: 2023-02-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_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index e604d5fc2feff..53c7207c0fbe7 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 1188523fd37e5..a820e75920c0e 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: 2023-02-12 +date: 2023-02-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 838ae7c1b0f52..7ba7b0b6a1e0c 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: 2023-02-12 +date: 2023-02-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 c274db0874737..ac07a7ea2f920 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: 2023-02-12 +date: 2023-02-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 025adba855b7e..62598444ca7ce 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: 2023-02-12 +date: 2023-02-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 f9ab8a4d3ad9a..bc5d037ce4284 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: 2023-02-12 +date: 2023-02-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_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 09ddbcc684acc..5a3405751c0df 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index a756ec7493e6c..b571e6d907980 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index d61b1e67bcda2..98d507d216872 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: 2023-02-12 +date: 2023-02-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_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index ab641d0705794..58c0460ce917b 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 1d01af6253da4..c792afe50823a 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index efedfbd55d0fa..21d695fdcd47e 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 91116f700bf36..c6f339a01a1e9 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: 2023-02-12 +date: 2023-02-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_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 48f946b27648d..b157058d2446d 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 1e00bdd7c354c..621f886c51be5 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: 2023-02-12 +date: 2023-02-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 ee22840f57ddd..9386be13e253a 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: 2023-02-12 +date: 2023-02-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 6cad019bb304f..bc05ebfa6a281 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: 2023-02-12 +date: 2023-02-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_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index 8f547163edd26..4c11bde76d985 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index d543066fec938..bf615de64694d 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: 2023-02-12 +date: 2023-02-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 41ee7f82ec2f5..b53754946ed0f 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: 2023-02-12 +date: 2023-02-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 18ad9c8aa5ec0..084789658465b 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: 2023-02-12 +date: 2023-02-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 18f9708fd926e..b6ddd0c5b13f2 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index b33b62453b668..4569cc6b94e0e 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index e5f35445b9a22..2dd5b0a4ee296 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index b01568beba3e5..f6bf1f58fa374 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 549a477cd57b7..08531727639c9 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: 2023-02-12 +date: 2023-02-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_rison.mdx b/api_docs/kbn_rison.mdx index 3dd1f4c3cc96c..453e61b915936 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 65786d04edb7f..d08acd1edcc7c 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: 2023-02-12 +date: 2023-02-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 a9276397a2ddf..d43c78f7d9108 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 0d1ddf4f774e9..3058573357bea 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index cec9fb59041f5..c40592651df79 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: 2023-02-12 +date: 2023-02-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_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 12ef7675b6152..b20a686fcd813 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index d7cad2123535b..5970e9d1083dc 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: 2023-02-12 +date: 2023-02-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 db65cafe6ffe3..cb70e7eede04a 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: 2023-02-12 +date: 2023-02-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 c3de52ce88cf0..1230c51fb2441 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: 2023-02-12 +date: 2023-02-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 4240467f723a7..e82973502bc9b 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: 2023-02-12 +date: 2023-02-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 e09bce70315eb..f8f39682e1faf 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: 2023-02-12 +date: 2023-02-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 92586aeed3e7a..16442d24b6ab3 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: 2023-02-12 +date: 2023-02-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 a9c48e628ff36..3a17ab676906d 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: 2023-02-12 +date: 2023-02-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 9b274b0c07de9..87632efe414c5 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: 2023-02-12 +date: 2023-02-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 8dac38639fefc..0df26aabedc21 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: 2023-02-12 +date: 2023-02-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 607e3f25f483c..b06a5a5c0b4ac 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: 2023-02-12 +date: 2023-02-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 7dc979e2063be..283414599762d 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: 2023-02-12 +date: 2023-02-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 08cd1d4ca6016..e7254db2141ae 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: 2023-02-12 +date: 2023-02-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 8d9d2513bd523..bd44e4257cb58 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: 2023-02-12 +date: 2023-02-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 ee3cf3795a30d..2c0099ae8bbed 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: 2023-02-12 +date: 2023-02-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 a0185c9a0913f..7702e974410a2 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: 2023-02-12 +date: 2023-02-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_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 24dbce79794e0..dd00049143c28 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index 71384e323fe4c..5c7292571880e 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 91eb47fdac066..2ecc8262beab8 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.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 a888ae60b0ce1..713dd67bc8642 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: 2023-02-12 +date: 2023-02-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 1073d331fe850..800c621fbb43c 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: 2023-02-12 +date: 2023-02-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 7d5f9cdcfc325..96c34d593da01 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: 2023-02-12 +date: 2023-02-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 a92e0e4224d8c..948bfb169e965 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: 2023-02-12 +date: 2023-02-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_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 62b33bf581413..546e1c0906e0c 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 11186bb549cf9..ed7e027fd51f3 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index 1bd7e7f7a2eae..9ba0ed2ad0950 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 0fedef4d0ec7c..689c4ccc4e823 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 0afbc5534148b..77e32631b9bec 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 6f03cc2d58a15..20838f81909a4 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 761912fc20338..3feb6f3bbbe4e 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index 2608940b0a9e3..c4f8842d34235 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.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 f5065e1087525..2502679faa79f 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: 2023-02-12 +date: 2023-02-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_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 69e9ede7ba8c6..6112b556e4a67 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 3a9b8b0aa0b4b..2fb00d3271803 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_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 250c7d2f3c072..5ae4843fe3981 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: 2023-02-12 +date: 2023-02-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 91eaa9e065423..1b4bc814a5531 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: 2023-02-12 +date: 2023-02-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 55f0803ec5121..52cd48fdc6dd5 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: 2023-02-12 +date: 2023-02-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 58ce40e2e26fc..c4cc54de7d923 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: 2023-02-12 +date: 2023-02-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 bd0c5195e0c2d..3275c06c40df3 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: 2023-02-12 +date: 2023-02-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 6a0d223ffa1ca..90d4e2a7adf06 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: 2023-02-12 +date: 2023-02-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 cda6ee5898546..14929e8dd6d94 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: 2023-02-12 +date: 2023-02-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 7aa80bf8e940d..37a46abdcebce 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: 2023-02-12 +date: 2023-02-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 3fef93cf8f810..1f336e80066be 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: 2023-02-12 +date: 2023-02-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 67758e5ec00a2..9f41a763a7f91 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: 2023-02-12 +date: 2023-02-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 3c8cde52e65e6..e79fb4d3c816b 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: 2023-02-12 +date: 2023-02-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 80db42d03b672..6f2db9ad9c5f8 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: 2023-02-12 +date: 2023-02-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 13ca5d30946ea..7c6679869eff1 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: 2023-02-12 +date: 2023-02-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_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index e879b87a01ea4..3e82007577f93 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 8b444334070c4..0d79c34e1a046 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: 2023-02-12 +date: 2023-02-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 74f66b03cc200..c8a053c8e61f0 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: 2023-02-12 +date: 2023-02-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 9eb1a6551c7e0..cf199168f5b2f 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: 2023-02-12 +date: 2023-02-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 de158bc8602d7..988ef3033ca73 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: 2023-02-12 +date: 2023-02-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 1399e8bce9110..af50394e9ae21 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: 2023-02-12 +date: 2023-02-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_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index c9e4e0846acfe..67659171defbd 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 9db92878ef32b..520cb4004d740 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: 2023-02-12 +date: 2023-02-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_std.mdx b/api_docs/kbn_std.mdx index 4f56cbd54b5e4..7b7cd37e84bdc 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: 2023-02-12 +date: 2023-02-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 40619e42e6cdd..bf7ad4ef7e82a 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: 2023-02-12 +date: 2023-02-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 aed5e43678214..7997fc4557d76 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: 2023-02-12 +date: 2023-02-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 96e6e025b495b..a83de1ea918d3 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: 2023-02-12 +date: 2023-02-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 d157803bdf0e7..283e00a9e1b24 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: 2023-02-12 +date: 2023-02-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 b5a99954970cb..290b9c56dc787 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: 2023-02-12 +date: 2023-02-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_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 95a3d409d960b..f8b259b11f915 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 14c8f8c365192..2481fa9f3b945 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index e02d37029a7b8..a46aa622abe9a 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 48f55f8cdab26..ddfd23a3a5502 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: 2023-02-12 +date: 2023-02-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_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index d5ea7dc307b58..6a09f3fae55f2 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 129e5b327b7d5..689b8bc2234a7 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 2ba2eed94167a..f510d34903490 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: 2023-02-12 +date: 2023-02-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 34b45f7e2f1de..77fdb9ab2e142 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: 2023-02-12 +date: 2023-02-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 d7fe0e1f29c58..44ba603c98c1f 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: 2023-02-12 +date: 2023-02-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 1251147f597b8..3c9ca5f688bc9 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: 2023-02-12 +date: 2023-02-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 e2affc657b666..b9263f3934050 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: 2023-02-12 +date: 2023-02-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 088262f41911e..bb542805a69f3 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: 2023-02-12 +date: 2023-02-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 b24cbc3611687..2849788e17b07 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: 2023-02-12 +date: 2023-02-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 8c65d6cd4cb0d..53890e0c5aed0 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: 2023-02-12 +date: 2023-02-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 4879976f5cac8..01bbf1cc3692e 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: 2023-02-12 +date: 2023-02-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 7ea675e391f7a..b707a04864ede 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: 2023-02-12 +date: 2023-02-13 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 9ea358b577a11..9fa245e331cb7 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: 2023-02-12 +date: 2023-02-13 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 d72de6e2f6b0d..0ea740f1706f4 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: 2023-02-12 +date: 2023-02-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 22bc063ea0560..e8975328bdd65 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: 2023-02-12 +date: 2023-02-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 3be58adbad309..9826f4f96dacb 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: 2023-02-12 +date: 2023-02-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 21c6044fd4b80..39e39d6333814 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: 2023-02-12 +date: 2023-02-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 89ef659dd4bf6..b2824cb174e10 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: 2023-02-12 +date: 2023-02-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 cbe35a21f698d..644623dca9238 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: 2023-02-12 +date: 2023-02-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 433a49e3099e0..8ed6069ab0761 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: 2023-02-12 +date: 2023-02-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 7fb73917388e6..c62094946f441 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: 2023-02-12 +date: 2023-02-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 2fbb1b318e1b9..9ad61bd757a64 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: 2023-02-12 +date: 2023-02-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 61c6190c1699e..ef64b46221a91 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: 2023-02-12 +date: 2023-02-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 d50ced9b141fe..26e2a38fa6e0b 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: 2023-02-12 +date: 2023-02-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 8ffde3f2a5246..c219815c61506 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index f37ae14f9f7f9..9c175656ce6e5 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 5ee04f3aa5b4d..3fa43ac682ae4 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: 2023-02-12 +date: 2023-02-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 2233b1d163caa..582736a831e2e 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: 2023-02-12 +date: 2023-02-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 920f89d5dd592..a608234e314ff 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 7babc85b689d0..72e33ef7a002e 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 79a4f9c4b3312..ecdb36a0c35b3 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index cab1b47a0cc52..ab0f16134c3d6 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: 2023-02-12 +date: 2023-02-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 f83e1cd4d9f6b..3d2cfdd706a07 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: 2023-02-12 +date: 2023-02-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 24e4816a094e3..d39a12e96c625 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: 2023-02-12 +date: 2023-02-13 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 b148c96cb8870..05243f30e862a 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: 2023-02-12 +date: 2023-02-13 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 e704582521239..e5962fe15acbf 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: 2023-02-12 +date: 2023-02-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 68024dfd1fce5..83399d5aee837 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: 2023-02-12 +date: 2023-02-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 6f4148a2651ba..75c20dcee612e 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: 2023-02-12 +date: 2023-02-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 4e46282cb2c9e..eb11161bd3201 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: 2023-02-12 +date: 2023-02-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 f385a95ef28c2..2892131464fdb 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: 2023-02-12 +date: 2023-02-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 51cf5a558225b..ed859529d609d 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: 2023-02-12 +date: 2023-02-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 775d11b5183f2..aa2ad1bb158f3 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: 2023-02-12 +date: 2023-02-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 7f128cf52047b..d1fb5659c6922 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: 2023-02-12 +date: 2023-02-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 fa85a91fffdb4..edcc16163bfd3 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: 2023-02-12 +date: 2023-02-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 96d53474e2694..2673c43acfe2d 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: 2023-02-12 +date: 2023-02-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 80a2367635d53..abc795f10a11c 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: 2023-02-12 +date: 2023-02-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 c0990560a8d55..ee264c0490fdf 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: 2023-02-12 +date: 2023-02-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 042810f0aa516..54172422e2882 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: 2023-02-12 +date: 2023-02-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 f6067e04f73a1..0d2c8b22fe326 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: 2023-02-12 +date: 2023-02-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 dc29198ce1b28..78a66e91d60a1 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: 2023-02-12 +date: 2023-02-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 c45d7aa56e3a9..f3f8bac8ef053 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index c92477ac0703e..cd780ce57cfa2 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 5d23adfdc1cd3..ab837d198ef7d 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: 2023-02-12 +date: 2023-02-13 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 d8099e609f289..71454f14e5988 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: 2023-02-12 +date: 2023-02-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 6621a62db46b4..4b1e480727ec9 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: 2023-02-12 +date: 2023-02-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 a60a76f5f7390..6976781c35cba 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: 2023-02-12 +date: 2023-02-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 7c7e52fba4079..7bff3462cb8aa 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: 2023-02-12 +date: 2023-02-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 a605d335b18b5..cb3915bb23bfa 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: 2023-02-12 +date: 2023-02-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 83ded50c00790..9d55be5678b85 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: 2023-02-12 +date: 2023-02-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 5dd930c98f338..ce28d89951f5e 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: 2023-02-12 +date: 2023-02-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 65fd901e0e493..3502cbbd5077d 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: 2023-02-12 +date: 2023-02-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 d5f5485c5a776..ae7f45fb857ae 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: 2023-02-12 +date: 2023-02-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 372393dab6bb1..3a230359dc24f 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: 2023-02-12 +date: 2023-02-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 ee71b6b04ccba..81459c6aa9808 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 0d5b09955c021..cee3f30609fbd 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index cdab1164884bf..1d749925972f6 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: 2023-02-12 +date: 2023-02-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 ff22dcd00cbcc..e4922e0fb12a8 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: 2023-02-12 +date: 2023-02-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 00088ded9588c..49615f3bec49e 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: 2023-02-12 +date: 2023-02-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 a4dafb30b86b5..2bab1a92ced30 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: 2023-02-12 +date: 2023-02-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 b36f08a876fdc..0168070756467 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: 2023-02-12 +date: 2023-02-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 c37d2622619fd..7751260fc8a24 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: 2023-02-12 +date: 2023-02-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 e5fddc363d4a0..f47c85e4e8bd1 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: 2023-02-12 +date: 2023-02-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 0dc784c1fb4f9..50cabc3f8ac12 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: 2023-02-12 +date: 2023-02-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 bc0f008708eb1..27abcbd227516 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: 2023-02-12 +date: 2023-02-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 984cb16b3a592..dcb1c7358a000 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: 2023-02-12 +date: 2023-02-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 cd13672613337..67a8624c68790 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: 2023-02-12 +date: 2023-02-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 fabf20fa25843..f2a574b6f03d7 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: 2023-02-12 +date: 2023-02-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 1bcd48549da21..8768104eadb23 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: 2023-02-12 +date: 2023-02-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 8c5f83870800c..b9844cb52d9b1 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: 2023-02-12 +date: 2023-02-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 a911a4283e160..49b5463fd7950 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: 2023-02-12 +date: 2023-02-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 73878b07dd30e..8c4c8d4fd1c48 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: 2023-02-12 +date: 2023-02-13 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 9bc69324c0bd5f49a30634cea79e377e838b094c Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Mon, 13 Feb 2023 08:26:26 +0100 Subject: [PATCH 116/203] [Data View] Debounce data view index pattern input (#150722) Closes https://github.com/elastic/kibana/issues/128581 ## Summary This PR adds debounce to the logic of fetching indices which are matching the input value. --- .../components/data_view_editor_flyout_content.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx index 42426ccb99d92..d78f54995df1d 100644 --- a/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx +++ b/src/plugins/data_view_editor/public/components/data_view_editor_flyout_content.tsx @@ -15,7 +15,7 @@ import { EuiLoadingSpinner, EuiLink, } from '@elastic/eui'; - +import useDebounce from 'react-use/lib/useDebounce'; import { i18n } from '@kbn/i18n'; import useObservable from 'react-use/lib/useObservable'; import { INDEX_PATTERN_TYPE } from '@kbn/data-views-plugin/public'; @@ -167,9 +167,13 @@ const IndexPatternEditorFlyoutContentComponent = ({ const rollupIndex = useObservable(dataViewEditorService.rollupIndex$); const rollupIndicesCapabilities = useObservable(dataViewEditorService.rollupIndicesCaps$, {}); - useEffect(() => { - dataViewEditorService.setIndexPattern(title); - }, [dataViewEditorService, title]); + useDebounce( + () => { + dataViewEditorService.setIndexPattern(title); + }, + 250, + [dataViewEditorService, title] + ); useEffect(() => { dataViewEditorService.setAllowHidden(allowHidden); From 5580860863ebe0783025a7e99a9657ea716545b3 Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Mon, 13 Feb 2023 09:09:05 +0100 Subject: [PATCH 117/203] [Discover] Hide 'Toggle dialog with details' tooltip when 'Expanded document' flyout is opened or dismissed (#150438) Closes https://github.com/elastic/kibana/issues/148849 This PR closes the tooltip: * right after the button is pressed * and after the flyout is dismissed and focus returned to the button --- .../discover_grid_expand_button.tsx | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx index dfe44dbb2edbb..1a127f3639432 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx +++ b/src/plugins/discover/public/components/discover_grid/discover_grid_expand_button.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useContext, useEffect } from 'react'; +import React, { useContext, useEffect, useRef, useState } from 'react'; import { EuiButtonIcon, EuiDataGridCellValueElementProps, EuiToolTip } from '@elastic/eui'; import { euiLightVars as themeLight, euiDarkVars as themeDark } from '@kbn/ui-theme'; import { i18n } from '@kbn/i18n'; @@ -17,8 +17,11 @@ import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../discover_tour'; * Button to expand a given row */ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => { + const toolTipRef = useRef(null); + const [pressed, setPressed] = useState(false); const { expanded, setExpanded, rows, isDarkMode } = useContext(DiscoverGridContext); const current = rows[rowIndex]; + useEffect(() => { if (current.isAnchor) { setCellProps({ @@ -43,19 +46,34 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle const testSubj = current.isAnchor ? 'docTableExpandToggleColumnAnchor' : 'docTableExpandToggleColumn'; + + useEffect(() => { + if (!isCurrentRowExpanded && pressed) { + setPressed(false); + setTimeout(() => { + toolTipRef.current?.hideToolTip(); + }, 100); + } + }, [isCurrentRowExpanded, setPressed, pressed]); + if (!setExpanded) { return null; } return ( - + setExpanded?.(isCurrentRowExpanded ? undefined : current)} + onClick={() => { + const nextHit = isCurrentRowExpanded ? undefined : current; + toolTipRef.current?.hideToolTip(); + setPressed(Boolean(nextHit)); + setExpanded?.(nextHit); + }} color={isCurrentRowExpanded ? 'primary' : 'text'} iconType={isCurrentRowExpanded ? 'minimize' : 'expand'} isSelected={isCurrentRowExpanded} From e00d914135bfbc9013f5f755c1f4c850576a111a Mon Sep 17 00:00:00 2001 From: mohamedhamed-ahmed Date: Mon, 13 Feb 2023 09:37:52 +0000 Subject: [PATCH 118/203] chore(bug): fix control alignments in invetory page (#150897) ## Summary The current version of the Inventory shows the options for changes the style of the waffle map in the middle instead of against the right side of the screen. closes #150423 **Before** Screenshot 2023-02-10 at 15 09 18 **After** Screenshot 2023-02-10 at 15 08 57 --- .../public/pages/metrics/inventory_view/components/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx index 8938e1960d3d9..afd069dd0e8eb 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/layout.tsx @@ -150,7 +150,7 @@ export const Layout = React.memo( responsive={false} css={css` margin: 0; - justifycontent: 'end'; + justify-content: flex-end; `} > {view === 'map' && ( From f3c540d14963b35d3077d42685e1ce5774a77a73 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Mon, 13 Feb 2023 11:43:14 +0100 Subject: [PATCH 119/203] [CM] Setup basic client content type registry, support custom crud for content type (#150452) ## Summary Close https://github.com/elastic/kibana/issues/149216 Close https://github.com/elastic/kibana/issues/150552 Sets up a basic client content type registry which will be used for registering presentational data about the type. Also allows providing a custom `crud` for a content type. When provided it will be used for this content type when using the `contentClient` instead of the default `RpcClient` that uses the server-side registry. --- .../content_client/content_client.test.ts | 20 +++--- .../public/content_client/content_client.tsx | 18 +++--- .../content_client_mutation_hooks.test.tsx | 12 ++-- .../content_client_query_hooks.test.tsx | 12 ++-- .../crud_client.mock.ts} | 9 ++- .../public/crud_client/crud_client.ts | 14 +++++ .../public/crud_client/index.ts | 9 +++ .../content_management/public/index.ts | 2 +- .../content_management/public/plugin.ts | 17 +++-- .../public/registry/content_type.test.ts | 35 +++++++++++ .../public/registry/content_type.ts | 34 ++++++++++ .../registry/content_type_definition.ts | 42 +++++++++++++ .../public/registry/index.ts | 11 ++++ .../public/registry/registry.test.ts | 62 +++++++++++++++++++ .../public/registry/registry.ts | 32 ++++++++++ .../public/rpc_client/rpc_client.ts | 5 +- .../content_management/public/types.ts | 7 ++- src/plugins/content_management/tsconfig.json | 1 - 18 files changed, 297 insertions(+), 45 deletions(-) rename src/plugins/content_management/public/{rpc_client/rpc_client.mock.ts => crud_client/crud_client.mock.ts} (64%) create mode 100644 src/plugins/content_management/public/crud_client/crud_client.ts create mode 100644 src/plugins/content_management/public/crud_client/index.ts create mode 100644 src/plugins/content_management/public/registry/content_type.test.ts create mode 100644 src/plugins/content_management/public/registry/content_type.ts create mode 100644 src/plugins/content_management/public/registry/content_type_definition.ts create mode 100644 src/plugins/content_management/public/registry/index.ts create mode 100644 src/plugins/content_management/public/registry/registry.test.ts create mode 100644 src/plugins/content_management/public/registry/registry.ts diff --git a/src/plugins/content_management/public/content_client/content_client.test.ts b/src/plugins/content_management/public/content_client/content_client.test.ts index 74be9a7c6aecf..e8465206b5e0b 100644 --- a/src/plugins/content_management/public/content_client/content_client.test.ts +++ b/src/plugins/content_management/public/content_client/content_client.test.ts @@ -8,31 +8,31 @@ import { lastValueFrom } from 'rxjs'; import { takeWhile, toArray } from 'rxjs/operators'; -import type { RpcClient } from '../rpc_client'; -import { createRpcClientMock } from '../rpc_client/rpc_client.mock'; +import type { CrudClient } from '../crud_client'; +import { createCrudClientMock } from '../crud_client/crud_client.mock'; import { ContentClient } from './content_client'; import type { GetIn, CreateIn } from '../../common'; let contentClient: ContentClient; -let rpcClient: jest.Mocked; +let crudClient: jest.Mocked; beforeEach(() => { - rpcClient = createRpcClientMock(); - contentClient = new ContentClient(rpcClient); + crudClient = createCrudClientMock(); + contentClient = new ContentClient(() => crudClient); }); describe('#get', () => { it('calls rpcClient.get with input and returns output', async () => { const input: GetIn = { id: 'test', contentType: 'testType' }; const output = { test: 'test' }; - rpcClient.get.mockResolvedValueOnce(output); + crudClient.get.mockResolvedValueOnce(output); expect(await contentClient.get(input)).toEqual(output); - expect(rpcClient.get).toBeCalledWith(input); + expect(crudClient.get).toBeCalledWith(input); }); it('calls rpcClient.get$ with input and returns output', async () => { const input: GetIn = { id: 'test', contentType: 'testType' }; const output = { test: 'test' }; - rpcClient.get.mockResolvedValueOnce(output); + crudClient.get.mockResolvedValueOnce(output); const get$ = contentClient.get$(input).pipe( takeWhile((result) => { return result.data == null; @@ -54,9 +54,9 @@ describe('#create', () => { it('calls rpcClient.create with input and returns output', async () => { const input: CreateIn = { contentType: 'testType', data: { foo: 'bar' } }; const output = { test: 'test' }; - rpcClient.create.mockImplementation(() => Promise.resolve(output)); + crudClient.create.mockResolvedValueOnce(output); expect(await contentClient.create(input)).toEqual(output); - expect(rpcClient.create).toBeCalledWith(input); + expect(crudClient.create).toBeCalledWith(input); }); }); diff --git a/src/plugins/content_management/public/content_client/content_client.tsx b/src/plugins/content_management/public/content_client/content_client.tsx index 72c9ea9f88929..e10af79ffefda 100644 --- a/src/plugins/content_management/public/content_client/content_client.tsx +++ b/src/plugins/content_management/public/content_client/content_client.tsx @@ -8,7 +8,7 @@ import { QueryClient } from '@tanstack/react-query'; import { createQueryObservable } from './query_observable'; -import type { RpcClient } from '../rpc_client'; +import type { CrudClient } from '../crud_client'; import type { CreateIn, GetIn } from '../../common'; const queryKeyBuilder = { @@ -18,12 +18,16 @@ const queryKeyBuilder = { }, }; -const createQueryOptionBuilder = ({ rpcClient }: { rpcClient: RpcClient }) => { +const createQueryOptionBuilder = ({ + crudClientProvider, +}: { + crudClientProvider: (contentType: string) => CrudClient; +}) => { return { get: (input: I) => { return { queryKey: queryKeyBuilder.item(input.contentType, input.id), - queryFn: () => rpcClient.get(input), + queryFn: () => crudClientProvider(input.contentType).get(input), }; }, }; @@ -33,10 +37,10 @@ export class ContentClient { readonly queryClient: QueryClient; readonly queryOptionBuilder: ReturnType; - constructor(private readonly rpcClient: RpcClient) { + constructor(private readonly crudClientProvider: (contentType: string) => CrudClient) { this.queryClient = new QueryClient(); this.queryOptionBuilder = createQueryOptionBuilder({ - rpcClient: this.rpcClient, + crudClientProvider: this.crudClientProvider, }); } @@ -48,7 +52,7 @@ export class ContentClient { return createQueryObservable(this.queryClient, this.queryOptionBuilder.get(input)); } - create(input: I): Promise { - return this.rpcClient.create(input); + create(input: I): Promise { + return this.crudClientProvider(input.contentType).create(input); } } diff --git a/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx b/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx index a7b9d4a5dfc7a..dfbf960e605d0 100644 --- a/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx +++ b/src/plugins/content_management/public/content_client/content_client_mutation_hooks.test.tsx @@ -10,16 +10,16 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { ContentClientProvider } from './content_client_context'; import { ContentClient } from './content_client'; -import { RpcClient } from '../rpc_client'; -import { createRpcClientMock } from '../rpc_client/rpc_client.mock'; +import { CrudClient } from '../crud_client'; +import { createCrudClientMock } from '../crud_client/crud_client.mock'; import { useCreateContentMutation } from './content_client_mutation_hooks'; import type { CreateIn } from '../../common'; let contentClient: ContentClient; -let rpcClient: jest.Mocked; +let crudClient: jest.Mocked; beforeEach(() => { - rpcClient = createRpcClientMock(); - contentClient = new ContentClient(rpcClient); + crudClient = createCrudClientMock(); + contentClient = new ContentClient(() => crudClient); }); const Wrapper: React.FC = ({ children }) => ( @@ -30,7 +30,7 @@ describe('useCreateContentMutation', () => { test('should call rpcClient.create with input and resolve with output', async () => { const input: CreateIn = { contentType: 'testType', data: { foo: 'bar' } }; const output = { test: 'test' }; - rpcClient.create.mockImplementation(() => Promise.resolve(output)); + crudClient.create.mockResolvedValueOnce(output); const { result, waitFor } = renderHook(() => useCreateContentMutation(), { wrapper: Wrapper }); result.current.mutate(input); diff --git a/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx b/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx index 07a22bb5154d5..4b88b32b5e5c8 100644 --- a/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx +++ b/src/plugins/content_management/public/content_client/content_client_query_hooks.test.tsx @@ -10,16 +10,16 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { ContentClientProvider } from './content_client_context'; import { ContentClient } from './content_client'; -import { RpcClient } from '../rpc_client'; -import { createRpcClientMock } from '../rpc_client/rpc_client.mock'; +import { CrudClient } from '../crud_client'; +import { createCrudClientMock } from '../crud_client/crud_client.mock'; import { useGetContentQuery } from './content_client_query_hooks'; import type { GetIn } from '../../common'; let contentClient: ContentClient; -let rpcClient: jest.Mocked; +let crudClient: jest.Mocked; beforeEach(() => { - rpcClient = createRpcClientMock(); - contentClient = new ContentClient(rpcClient); + crudClient = createCrudClientMock(); + contentClient = new ContentClient(() => crudClient); }); const Wrapper: React.FC = ({ children }) => ( @@ -30,7 +30,7 @@ describe('useGetContentQuery', () => { test('should call rpcClient.get with input and resolve with output', async () => { const input: GetIn = { id: 'test', contentType: 'testType' }; const output = { test: 'test' }; - rpcClient.get.mockImplementation(() => Promise.resolve(output)); + crudClient.get.mockResolvedValueOnce(output); const { result, waitFor } = renderHook(() => useGetContentQuery(input), { wrapper: Wrapper }); await waitFor(() => result.current.isSuccess); expect(result.current.data).toEqual(output); diff --git a/src/plugins/content_management/public/rpc_client/rpc_client.mock.ts b/src/plugins/content_management/public/crud_client/crud_client.mock.ts similarity index 64% rename from src/plugins/content_management/public/rpc_client/rpc_client.mock.ts rename to src/plugins/content_management/public/crud_client/crud_client.mock.ts index ad8cd384dd0e5..abcb551b33cb9 100644 --- a/src/plugins/content_management/public/rpc_client/rpc_client.mock.ts +++ b/src/plugins/content_management/public/crud_client/crud_client.mock.ts @@ -6,13 +6,12 @@ * Side Public License, v 1. */ -import type { RpcClient } from './rpc_client'; -import { PublicMethodsOf } from '@kbn/utility-types'; +import type { CrudClient } from './crud_client'; -export const createRpcClientMock = (): jest.Mocked => { - const mock: jest.Mocked> = { +export const createCrudClientMock = (): jest.Mocked => { + const mock: jest.Mocked = { get: jest.fn((input) => Promise.resolve({} as any)), create: jest.fn((input) => Promise.resolve({} as any)), }; - return mock as jest.Mocked; + return mock; }; diff --git a/src/plugins/content_management/public/crud_client/crud_client.ts b/src/plugins/content_management/public/crud_client/crud_client.ts new file mode 100644 index 0000000000000..f233eb3f62e37 --- /dev/null +++ b/src/plugins/content_management/public/crud_client/crud_client.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 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 { GetIn, CreateIn } from '../../common'; + +export interface CrudClient { + get(input: I): Promise; + create(input: I): Promise; +} diff --git a/src/plugins/content_management/public/crud_client/index.ts b/src/plugins/content_management/public/crud_client/index.ts new file mode 100644 index 0000000000000..25c360f99115e --- /dev/null +++ b/src/plugins/content_management/public/crud_client/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 type { CrudClient } from './crud_client'; diff --git a/src/plugins/content_management/public/index.ts b/src/plugins/content_management/public/index.ts index 786c4f212481f..0bf75e9d1087a 100644 --- a/src/plugins/content_management/public/index.ts +++ b/src/plugins/content_management/public/index.ts @@ -12,4 +12,4 @@ export function plugin() { return new ContentManagementPlugin(); } -export type { ContentManagementPublicStart } from './types'; +export type { ContentManagementPublicStart, ContentManagementPublicSetup } from './types'; diff --git a/src/plugins/content_management/public/plugin.ts b/src/plugins/content_management/public/plugin.ts index 77d0bcc6039bc..d82e2fadfb3e6 100644 --- a/src/plugins/content_management/public/plugin.ts +++ b/src/plugins/content_management/public/plugin.ts @@ -14,6 +14,7 @@ import { StartDependencies, } from './types'; import type { ContentClient } from './content_client'; +import type { ContentTypeRegistry } from './registry'; export class ContentManagementPlugin implements @@ -25,14 +26,20 @@ export class ContentManagementPlugin > { public setup(core: CoreSetup, deps: SetupDependencies) { - return {}; + // don't actually expose the client and the registry until it is used to avoid increasing bundle size + return { + registry: {} as ContentTypeRegistry, + }; } public start(core: CoreStart, deps: StartDependencies) { - // don't actually expose the client until it is used to avoid increasing bundle size + // don't actually expose the client and the registry until it is used to avoid increasing bundle size // const rpcClient = new RpcClient(core.http); - // const contentClient = new ContentClient(rpcClient); - // return { client: contentClient }; - return { client: {} as ContentClient }; + // const contentTypeRegistry = new ContentTypeRegistry(); + // const contentClient = new ContentClient( + // (contentType) => contentTypeRegistry.get(contentType)?.crud() ?? rpcClient + // ); + // return { client: contentClient, registry: contentTypeRegistry }; + return { client: {} as ContentClient, registry: {} as ContentTypeRegistry }; } } diff --git a/src/plugins/content_management/public/registry/content_type.test.ts b/src/plugins/content_management/public/registry/content_type.test.ts new file mode 100644 index 0000000000000..c6a5e18fd6f6c --- /dev/null +++ b/src/plugins/content_management/public/registry/content_type.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ContentType } from './content_type'; +import type { ContentTypeDefinition } from './content_type_definition'; + +test('create a content type with just an id', () => { + const type = new ContentType({ id: 'test' }); + + expect(type.id()).toBe('test'); + expect(type.name()).toBe('test'); + expect(type.icon()).toBe('questionInCircle'); + expect(type.description()).toBe(''); +}); + +test('create a content type with all the full definition', () => { + const definition: ContentTypeDefinition = { + id: 'test', + name: 'Test', + icon: 'test', + description: 'Test description', + }; + const type = new ContentType(definition); + + expect(type.id()).toBe(definition.id); + expect(type.name()).toBe(definition.name); + expect(type.icon()).toBe(definition.icon); + expect(type.description()).toBe(definition.description); + expect(type.definition).toEqual(definition); +}); diff --git a/src/plugins/content_management/public/registry/content_type.ts b/src/plugins/content_management/public/registry/content_type.ts new file mode 100644 index 0000000000000..213a1c5427e0e --- /dev/null +++ b/src/plugins/content_management/public/registry/content_type.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. + */ + +import { ContentTypeDefinition } from './content_type_definition'; +import type { CrudClient } from '../crud_client'; + +export class ContentType { + constructor(public readonly definition: ContentTypeDefinition) {} + + id(): string { + return this.definition.id; + } + + name(): string { + return this.definition.name ?? this.id(); + } + + description(): string { + return this.definition.description ?? ''; + } + + icon(): string { + return this.definition.icon ?? 'questionInCircle'; + } + + crud(): CrudClient | undefined { + return this.definition.crud; + } +} diff --git a/src/plugins/content_management/public/registry/content_type_definition.ts b/src/plugins/content_management/public/registry/content_type_definition.ts new file mode 100644 index 0000000000000..42a60ed4793fd --- /dev/null +++ b/src/plugins/content_management/public/registry/content_type_definition.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 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 { CrudClient } from '../crud_client'; + +/** + * Content type definition as it is registered in the content registry. + */ +export interface ContentTypeDefinition { + /** + * ID of the type. Must be unique. Like "dashboard", "visualization", etc. + */ + id: string; + + /** + * Human-readable name of the type. Like "Dashboard", "Visualization", etc. + */ + name?: string; + + /** + * Human-readable description of the type. + */ + description?: string; + + /** + * Icon to use for this type. Usually an EUI icon type. + * + * @see https://elastic.github.io/eui/#/display/icons + */ + icon?: string; + + /** + * CRUD client to use for this type. + * If not provided the default CRUD client is used assuming that this type has a server-side content registry + */ + crud?: CrudClient; +} diff --git a/src/plugins/content_management/public/registry/index.ts b/src/plugins/content_management/public/registry/index.ts new file mode 100644 index 0000000000000..857cb9f60a6ef --- /dev/null +++ b/src/plugins/content_management/public/registry/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 type { ContentTypeDefinition } from './content_type_definition'; +export { ContentType } from './content_type'; +export { ContentTypeRegistry } from './registry'; diff --git a/src/plugins/content_management/public/registry/registry.test.ts b/src/plugins/content_management/public/registry/registry.test.ts new file mode 100644 index 0000000000000..f6284ddd31f64 --- /dev/null +++ b/src/plugins/content_management/public/registry/registry.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ContentTypeRegistry } from './registry'; + +let registry: ContentTypeRegistry; + +beforeEach(() => { + registry = new ContentTypeRegistry(); +}); + +test('registering a content type', () => { + const type = registry.register({ + id: 'test', + name: 'Test', + icon: 'test', + description: 'Test description', + }); + + expect(type.id()).toBe('test'); + expect(type.name()).toBe('Test'); + expect(type.icon()).toBe('test'); + expect(type.description()).toBe('Test description'); +}); + +test('registering already registered content type throws', () => { + registry.register({ + id: 'test', + }); + + expect(() => registry.register({ id: 'test' })).toThrowErrorMatchingInlineSnapshot( + `"Content type with id \\"test\\" already registered."` + ); +}); + +test('getting non registered content returns undefined', () => { + expect(registry.get('test')).toBeUndefined(); +}); + +test('get', () => { + const type = registry.register({ + id: 'test', + }); + + expect(registry.get('test')).toEqual(type); +}); + +test('getAll', () => { + registry.register({ + id: 'test1', + }); + registry.register({ + id: 'test2', + }); + + expect(registry.getAll()).toHaveLength(2); +}); diff --git a/src/plugins/content_management/public/registry/registry.ts b/src/plugins/content_management/public/registry/registry.ts new file mode 100644 index 0000000000000..6648888122bc0 --- /dev/null +++ b/src/plugins/content_management/public/registry/registry.ts @@ -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 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 { ContentTypeDefinition } from './content_type_definition'; +import { ContentType } from './content_type'; + +export class ContentTypeRegistry { + private readonly types: Map = new Map(); + + public register(definition: ContentTypeDefinition): ContentType { + if (this.types.has(definition.id)) { + throw new Error(`Content type with id "${definition.id}" already registered.`); + } + const type = new ContentType(definition); + this.types.set(type.id(), type); + + return type; + } + + public get(id: string): ContentType | undefined { + return this.types.get(id); + } + + public getAll(): ContentType[] { + return Array.from(this.types.values()); + } +} diff --git a/src/plugins/content_management/public/rpc_client/rpc_client.ts b/src/plugins/content_management/public/rpc_client/rpc_client.ts index 1cfb2b12f02a5..b5b7b7804d9d1 100644 --- a/src/plugins/content_management/public/rpc_client/rpc_client.ts +++ b/src/plugins/content_management/public/rpc_client/rpc_client.ts @@ -9,15 +9,16 @@ import { HttpSetup } from '@kbn/core/public'; import { API_ENDPOINT } from '../../common'; import type { GetIn, CreateIn, ProcedureName } from '../../common'; +import type { CrudClient } from '../crud_client/crud_client'; -export class RpcClient { +export class RpcClient implements CrudClient { constructor(private http: { post: HttpSetup['post'] }) {} public get(input: I): Promise { return this.sendMessage('get', input); } - public create(input: I): Promise { + public create(input: I): Promise { return this.sendMessage('create', input); } diff --git a/src/plugins/content_management/public/types.ts b/src/plugins/content_management/public/types.ts index dcee504cd8d6b..b6f2e1b2da1a1 100644 --- a/src/plugins/content_management/public/types.ts +++ b/src/plugins/content_management/public/types.ts @@ -7,6 +7,7 @@ */ import type { ContentClient } from './content_client'; +import type { ContentTypeRegistry } from './registry'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SetupDependencies {} @@ -14,9 +15,11 @@ export interface SetupDependencies {} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface StartDependencies {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface ContentManagementPublicSetup {} +export interface ContentManagementPublicSetup { + registry: Pick; +} export interface ContentManagementPublicStart { client: ContentClient; + registry: Pick; } diff --git a/src/plugins/content_management/tsconfig.json b/src/plugins/content_management/tsconfig.json index 0c998149f88b8..8a207e0e42ca3 100644 --- a/src/plugins/content_management/tsconfig.json +++ b/src/plugins/content_management/tsconfig.json @@ -7,7 +7,6 @@ "kbn_references": [ "@kbn/core", "@kbn/config-schema", - "@kbn/utility-types", ], "exclude": [ "target/**/*", From 99bb6fd2037f38eca30bdfbc076f8f5a533e86f1 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Mon, 13 Feb 2023 11:46:56 +0100 Subject: [PATCH 120/203] [Advanced Settings] Fix badge counter for global settings (#150869) ## Summary This PR fixes the badge count for Global settings, which was incorrectly showing there are results, when there were in fact none. Also, changing the owners of the `ui-settings` related packages and plugins from core to `shared-ux`. Screenshot 2023-02-10 at 13 04 58 ### Checklist Delete any items that are not applicable to this PR. ~- [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~ ~- [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials~ ~- [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios~ ~- [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/))~ ~- [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))~ ~- [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ ~- [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))~ ~- [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers)~ ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 16 ++++++++-------- .../kibana.jsonc | 2 +- .../core-ui-settings-browser-mocks/kibana.jsonc | 2 +- .../core-ui-settings-browser/kibana.jsonc | 2 +- .../core-ui-settings-common/kibana.jsonc | 2 +- .../kibana.jsonc | 2 +- .../core-ui-settings-server-mocks/kibana.jsonc | 2 +- .../core-ui-settings-server/kibana.jsonc | 2 +- src/plugins/advanced_settings/kibana.jsonc | 2 +- .../public/management_app/settings.tsx | 7 +++---- 10 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f4ceea12be49a..24c1a523c5c09 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -9,7 +9,7 @@ x-pack/test/alerting_api_integration/common/plugins/aad @elastic/response-ops packages/kbn-ace @elastic/platform-deployment-management x-pack/plugins/actions @elastic/response-ops x-pack/test/alerting_api_integration/common/plugins/actions_simulators @elastic/response-ops -src/plugins/advanced_settings @elastic/kibana-core +src/plugins/advanced_settings @elastic/appex-sharedux x-pack/packages/ml/aiops_components @elastic/ml-ui x-pack/plugins/aiops @elastic/ml-ui x-pack/packages/ml/aiops_utils @elastic/ml-ui @@ -270,13 +270,13 @@ packages/core/test-helpers/core-test-helpers-test-utils @elastic/kibana-core packages/core/theme/core-theme-browser @elastic/kibana-core packages/core/theme/core-theme-browser-internal @elastic/kibana-core packages/core/theme/core-theme-browser-mocks @elastic/kibana-core -packages/core/ui-settings/core-ui-settings-browser @elastic/kibana-core -packages/core/ui-settings/core-ui-settings-browser-internal @elastic/kibana-core -packages/core/ui-settings/core-ui-settings-browser-mocks @elastic/kibana-core -packages/core/ui-settings/core-ui-settings-common @elastic/kibana-core -packages/core/ui-settings/core-ui-settings-server @elastic/kibana-core -packages/core/ui-settings/core-ui-settings-server-internal @elastic/kibana-core -packages/core/ui-settings/core-ui-settings-server-mocks @elastic/kibana-core +packages/core/ui-settings/core-ui-settings-browser @elastic/appex-sharedux +packages/core/ui-settings/core-ui-settings-browser-internal @elastic/appex-sharedux +packages/core/ui-settings/core-ui-settings-browser-mocks @elastic/appex-sharedux +packages/core/ui-settings/core-ui-settings-common @elastic/appex-sharedux +packages/core/ui-settings/core-ui-settings-server @elastic/appex-sharedux +packages/core/ui-settings/core-ui-settings-server-internal @elastic/appex-sharedux +packages/core/ui-settings/core-ui-settings-server-mocks @elastic/appex-sharedux packages/core/usage-data/core-usage-data-base-server-internal @elastic/kibana-core packages/core/usage-data/core-usage-data-server @elastic/kibana-core packages/core/usage-data/core-usage-data-server-internal @elastic/kibana-core diff --git a/packages/core/ui-settings/core-ui-settings-browser-internal/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-browser-internal/kibana.jsonc index 1197ce3268992..8ed0f675a5e14 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-internal/kibana.jsonc +++ b/packages/core/ui-settings/core-ui-settings-browser-internal/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", "id": "@kbn/core-ui-settings-browser-internal", - "owner": "@elastic/kibana-core" + "owner": "@elastic/appex-sharedux" } diff --git a/packages/core/ui-settings/core-ui-settings-browser-mocks/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-browser-mocks/kibana.jsonc index 8f3d630732b6d..42af85121662e 100644 --- a/packages/core/ui-settings/core-ui-settings-browser-mocks/kibana.jsonc +++ b/packages/core/ui-settings/core-ui-settings-browser-mocks/kibana.jsonc @@ -2,5 +2,5 @@ "type": "shared-common", "id": "@kbn/core-ui-settings-browser-mocks", "devOnly": true, - "owner": "@elastic/kibana-core" + "owner": "@elastic/appex-sharedux" } diff --git a/packages/core/ui-settings/core-ui-settings-browser/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-browser/kibana.jsonc index 57036db46d663..2428df187ca31 100644 --- a/packages/core/ui-settings/core-ui-settings-browser/kibana.jsonc +++ b/packages/core/ui-settings/core-ui-settings-browser/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", "id": "@kbn/core-ui-settings-browser", - "owner": "@elastic/kibana-core" + "owner": "@elastic/appex-sharedux" } diff --git a/packages/core/ui-settings/core-ui-settings-common/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-common/kibana.jsonc index 9d12715c5ebf1..6ecff8c3c5be2 100644 --- a/packages/core/ui-settings/core-ui-settings-common/kibana.jsonc +++ b/packages/core/ui-settings/core-ui-settings-common/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", "id": "@kbn/core-ui-settings-common", - "owner": "@elastic/kibana-core" + "owner": "@elastic/appex-sharedux" } diff --git a/packages/core/ui-settings/core-ui-settings-server-internal/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-server-internal/kibana.jsonc index e0f62711171c2..f8d6cde5db4da 100644 --- a/packages/core/ui-settings/core-ui-settings-server-internal/kibana.jsonc +++ b/packages/core/ui-settings/core-ui-settings-server-internal/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", "id": "@kbn/core-ui-settings-server-internal", - "owner": "@elastic/kibana-core" + "owner": "@elastic/appex-sharedux" } diff --git a/packages/core/ui-settings/core-ui-settings-server-mocks/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-server-mocks/kibana.jsonc index f55c1ada332ee..5d91163b19f44 100644 --- a/packages/core/ui-settings/core-ui-settings-server-mocks/kibana.jsonc +++ b/packages/core/ui-settings/core-ui-settings-server-mocks/kibana.jsonc @@ -2,5 +2,5 @@ "type": "shared-common", "id": "@kbn/core-ui-settings-server-mocks", "devOnly": true, - "owner": "@elastic/kibana-core" + "owner": "@elastic/appex-sharedux" } diff --git a/packages/core/ui-settings/core-ui-settings-server/kibana.jsonc b/packages/core/ui-settings/core-ui-settings-server/kibana.jsonc index 11926aebbc873..f839dbc1f35a9 100644 --- a/packages/core/ui-settings/core-ui-settings-server/kibana.jsonc +++ b/packages/core/ui-settings/core-ui-settings-server/kibana.jsonc @@ -1,5 +1,5 @@ { "type": "shared-common", "id": "@kbn/core-ui-settings-server", - "owner": "@elastic/kibana-core" + "owner": "@elastic/appex-sharedux" } diff --git a/src/plugins/advanced_settings/kibana.jsonc b/src/plugins/advanced_settings/kibana.jsonc index 66444263b31a8..99362de44c891 100644 --- a/src/plugins/advanced_settings/kibana.jsonc +++ b/src/plugins/advanced_settings/kibana.jsonc @@ -1,7 +1,7 @@ { "type": "plugin", "id": "@kbn/advanced-settings-plugin", - "owner": "@elastic/kibana-core", + "owner": "@elastic/appex-sharedux", "plugin": { "id": "advancedSettings", "server": true, diff --git a/src/plugins/advanced_settings/public/management_app/settings.tsx b/src/plugins/advanced_settings/public/management_app/settings.tsx index e3f9ad5991ed9..9cf81ffff7fe0 100644 --- a/src/plugins/advanced_settings/public/management_app/settings.tsx +++ b/src/plugins/advanced_settings/public/management_app/settings.tsx @@ -281,19 +281,18 @@ export const Settings = (props: Props) => { return (queryParams[QUERY] as string) ?? ''; }; - const getQueryState = (search?: string, intialQuery = false): AdvancedSettingsState => { + const getQueryState = (search?: string, initialQuery = false): AdvancedSettingsState => { const queryString = getQueryText(search); - const query = getQuery(queryString, intialQuery); + const query = getQuery(queryString, initialQuery); const filteredSettings = { namespace: mapSettings(Query.execute(query, settings)), global: mapSettings(Query.execute(query, globalSettings)), }; - const footerQueryMatched = Object.keys(filteredSettings.namespace).length > 0; return { query, filteredSettings, - footerQueryMatched, + footerQueryMatched: initialQuery ? false : queryState.footerQueryMatched, }; }; From a2cf330eb7b14bc76d6f2ae824df2bc6debfbf60 Mon Sep 17 00:00:00 2001 From: Katerina Patticha Date: Mon, 13 Feb 2023 11:55:13 +0100 Subject: [PATCH 121/203] [APM] Include `mobile` in the default transaction type list (#150877) ## Summary closes https://github.com/elastic/kibana/issues/150851 1. Add mobile in the default types 2. Create a helper to get the transaction type based on the agent 3. Create a helper to check if it's the default transaction type 4. Fixes apm query path for mobile service maps Fixes https://user-images.githubusercontent.com/3369346/218103732-dede9ec7-d45c-4b2f-b927-ed131ddc23a4.mov TODO [ ] what to display here https://github.com/elastic/kibana/pull/150877/files#diff-3935a5663adb960f24c56f563d87dfceb983e007509d98cfef170b6417bb5af1R70 --- .../plugins/apm/common/transaction_types.ts | 29 +++++++++++++++++-- .../service_inventory/service_list/index.tsx | 8 ++--- .../popover/dependency_contents.tsx | 3 +- .../app/service_map/popover/edge_contents.tsx | 3 +- .../apm_service/apm_service_context.tsx | 11 ++----- .../get_transactions_per_minute.ts | 11 ++----- .../service_map/get_service_anomalies.ts | 9 ++---- .../get_service_map_service_node_info.ts | 12 ++------ .../get_service_transaction_stats.ts | 10 ++----- ...service_transaction_detailed_statistics.ts | 10 ++----- 10 files changed, 50 insertions(+), 56 deletions(-) diff --git a/x-pack/plugins/apm/common/transaction_types.ts b/x-pack/plugins/apm/common/transaction_types.ts index 87c14fbd496f7..cc2f5557819fa 100644 --- a/x-pack/plugins/apm/common/transaction_types.ts +++ b/x-pack/plugins/apm/common/transaction_types.ts @@ -5,6 +5,31 @@ * 2.0. */ -export const TRANSACTION_PAGE_LOAD = 'page-load'; +import { isRumAgentName, isMobileAgentName } from './agent_name'; + +const TRANSACTION_PAGE_LOAD = 'page-load'; +const TRANSACTION_MOBILE = 'mobile'; + export const TRANSACTION_REQUEST = 'request'; -export const TRANSACTION_ROUTE_CHANGE = 'route-change'; + +export const defaultTransactionTypes = [ + TRANSACTION_REQUEST, + TRANSACTION_PAGE_LOAD, + TRANSACTION_MOBILE, +]; + +export function getDefaultTransactionType(agentName?: string) { + if (isRumAgentName(agentName)) { + return TRANSACTION_PAGE_LOAD; + } + + if (isMobileAgentName(agentName)) { + return TRANSACTION_MOBILE; + } + + return TRANSACTION_REQUEST; +} + +export function isDefaultTransactionType(transactionType: string) { + return defaultTransactionTypes.includes(transactionType); +} diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/index.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/index.tsx index 0f7d64477b2f4..9241c8bcae7a5 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/index.tsx @@ -22,10 +22,7 @@ import { ServiceInventoryFieldName, ServiceListItem, } from '../../../../../common/service_inventory'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../../../common/transaction_types'; +import { isDefaultTransactionType } from '../../../../../common/transaction_types'; import { asMillisecondDuration, asPercent, @@ -311,8 +308,7 @@ export function ServiceList({ const showTransactionTypeColumn = items.some( ({ transactionType }) => - transactionType !== TRANSACTION_REQUEST && - transactionType !== TRANSACTION_PAGE_LOAD + transactionType && !isDefaultTransactionType(transactionType) ); const { diff --git a/x-pack/plugins/apm/public/components/app/service_map/popover/dependency_contents.tsx b/x-pack/plugins/apm/public/components/app/service_map/popover/dependency_contents.tsx index e7e678c4c528f..7141c856a36f2 100644 --- a/x-pack/plugins/apm/public/components/app/service_map/popover/dependency_contents.tsx +++ b/x-pack/plugins/apm/public/components/app/service_map/popover/dependency_contents.tsx @@ -39,7 +39,8 @@ export function DependencyContents({ const { query } = useAnyOfApmParams( '/service-map', - '/services/{serviceName}/service-map' + '/services/{serviceName}/service-map', + '/mobile-services/{serviceName}/service-map' ); const { offset, comparisonEnabled } = query; diff --git a/x-pack/plugins/apm/public/components/app/service_map/popover/edge_contents.tsx b/x-pack/plugins/apm/public/components/app/service_map/popover/edge_contents.tsx index 36bc1ba74fd56..aeb9a771bf31e 100644 --- a/x-pack/plugins/apm/public/components/app/service_map/popover/edge_contents.tsx +++ b/x-pack/plugins/apm/public/components/app/service_map/popover/edge_contents.tsx @@ -26,7 +26,8 @@ export function EdgeContents({ elementData }: ContentsProps) { const { query } = useAnyOfApmParams( '/service-map', - '/services/{serviceName}/service-map' + '/services/{serviceName}/service-map', + '/mobile-services/{serviceName}/service-map' ); const apmRouter = useApmRouter(); diff --git a/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx b/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx index bc8792e63375b..480a47dc31166 100644 --- a/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx +++ b/x-pack/plugins/apm/public/context/apm_service/apm_service_context.tsx @@ -8,11 +8,7 @@ import React, { createContext, ReactNode } from 'react'; import { useHistory } from 'react-router-dom'; import { History } from 'history'; -import { isRumAgentName } from '../../../common/agent_name'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../common/transaction_types'; +import { getDefaultTransactionType } from '../../../common/transaction_types'; import { useServiceTransactionTypesFetcher } from './use_service_transaction_types_fetcher'; import { useServiceAgentFetcher } from './use_service_agent_fetcher'; import { useAnyOfApmParams } from '../../hooks/use_apm_params'; @@ -142,10 +138,7 @@ export function getTransactionType({ if (isNoAgentAndNoTransactionTypesExists) return undefined; - // The default transaction type is "page-load" for RUM agents and "request" for all others - const defaultTransactionType = isRumAgentName(agentName) - ? TRANSACTION_PAGE_LOAD - : TRANSACTION_REQUEST; + const defaultTransactionType = getDefaultTransactionType(agentName); // If the default transaction type is not in transactionTypes the first in the list is returned const currentTransactionType = transactionTypes.includes( diff --git a/x-pack/plugins/apm/server/routes/observability_overview/get_transactions_per_minute.ts b/x-pack/plugins/apm/server/routes/observability_overview/get_transactions_per_minute.ts index 844cab9da1ca3..23c5b18297c9d 100644 --- a/x-pack/plugins/apm/server/routes/observability_overview/get_transactions_per_minute.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview/get_transactions_per_minute.ts @@ -6,10 +6,7 @@ */ import { rangeQuery } from '@kbn/observability-plugin/server'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../common/transaction_types'; +import { isDefaultTransactionType } from '../../../common/transaction_types'; import { TRANSACTION_TYPE } from '../../../common/es_fields/apm'; import { getDocumentTypeFilterForTransactions, @@ -82,10 +79,8 @@ export async function getTransactionsPerMinute({ } const topTransactionTypeBucket = - aggregations.transactionType.buckets.find( - ({ key: transactionType }) => - transactionType === TRANSACTION_REQUEST || - transactionType === TRANSACTION_PAGE_LOAD + aggregations.transactionType.buckets.find(({ key: transactionType }) => + isDefaultTransactionType(transactionType as string) ) || aggregations.transactionType.buckets[0]; return { diff --git a/x-pack/plugins/apm/server/routes/service_map/get_service_anomalies.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_anomalies.ts index 6a887b21fde74..182820a86ea08 100644 --- a/x-pack/plugins/apm/server/routes/service_map/get_service_anomalies.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_anomalies.ts @@ -14,10 +14,7 @@ import { rangeQuery } from '@kbn/observability-plugin/server'; import { getSeverity, ML_ERRORS } from '../../../common/anomaly_detection'; import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; import { getServiceHealthStatus } from '../../../common/service_health_status'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../common/transaction_types'; +import { defaultTransactionTypes } from '../../../common/transaction_types'; import { withApmSpan } from '../../utils/with_apm_span'; import { getMlJobsWithAPMGroup } from '../../lib/anomaly_detection/get_ml_jobs_with_apm_group'; import { MlClient } from '../../lib/helpers/get_ml_client'; @@ -64,8 +61,8 @@ export async function getServiceAnomalies({ ), { terms: { - // Only retrieving anomalies for transaction types "request" and "page-load" - by_field_value: [TRANSACTION_REQUEST, TRANSACTION_PAGE_LOAD], + // Only retrieving anomalies for default transaction types + by_field_value: defaultTransactionTypes, }, }, ] as estypes.QueryDslQueryContainer[], diff --git a/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.ts b/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.ts index bbcbd439443fc..9c7665ed97e2b 100644 --- a/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.ts +++ b/x-pack/plugins/apm/server/routes/service_map/get_service_map_service_node_info.ts @@ -17,10 +17,7 @@ import { TRANSACTION_TYPE, } from '../../../common/es_fields/apm'; import { NodeStats } from '../../../common/service_map'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../common/transaction_types'; +import { defaultTransactionTypes } from '../../../common/transaction_types'; import { environmentQuery } from '../../../common/utils/environment_query'; import { getOffsetInMs } from '../../../common/utils/get_offset_in_ms'; import { getBucketSizeForAggregatedTransactions } from '../../lib/helpers/get_bucket_size_for_aggregated_transactions'; @@ -144,7 +141,7 @@ async function getFailedTransactionsRateStats({ end, kuery: '', numBuckets, - transactionTypes: [TRANSACTION_REQUEST, TRANSACTION_PAGE_LOAD], + transactionTypes: defaultTransactionTypes, }); return { value: average, @@ -183,10 +180,7 @@ async function getTransactionStats({ ), { terms: { - [TRANSACTION_TYPE]: [ - TRANSACTION_REQUEST, - TRANSACTION_PAGE_LOAD, - ], + [TRANSACTION_TYPE]: defaultTransactionTypes, }, }, ], diff --git a/x-pack/plugins/apm/server/routes/services/get_services/get_service_transaction_stats.ts b/x-pack/plugins/apm/server/routes/services/get_services/get_service_transaction_stats.ts index 88f2e55682868..9d26304e57c6e 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services/get_service_transaction_stats.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services/get_service_transaction_stats.ts @@ -16,10 +16,7 @@ import { } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; import { ServiceGroup } from '../../../../common/service_groups'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../../common/transaction_types'; +import { isDefaultTransactionType } from '../../../../common/transaction_types'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { AgentName } from '../../../../typings/es_schemas/ui/fields/agent'; import { calculateThroughputWithRange } from '../../../lib/helpers/calculate_throughput'; @@ -144,9 +141,8 @@ export async function getServiceTransactionStats({ serviceStats: response.aggregations?.sample.services.buckets.map((bucket) => { const topTransactionTypeBucket = - bucket.transactionType.buckets.find( - ({ key }) => - key === TRANSACTION_REQUEST || key === TRANSACTION_PAGE_LOAD + bucket.transactionType.buckets.find(({ key }) => + isDefaultTransactionType(key as string) ) ?? bucket.transactionType.buckets[0]; return { diff --git a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts index a410036d4c52e..5e6d84039266e 100644 --- a/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/routes/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts @@ -13,10 +13,7 @@ import { TRANSACTION_TYPE, } from '../../../../common/es_fields/apm'; import { RollupInterval } from '../../../../common/rollup'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../../common/transaction_types'; +import { isDefaultTransactionType } from '../../../../common/transaction_types'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { getOffsetInMs } from '../../../../common/utils/get_offset_in_ms'; import { calculateThroughputWithInterval } from '../../../lib/helpers/calculate_throughput'; @@ -137,9 +134,8 @@ export async function getServiceTransactionDetailedStats({ return keyBy( response.aggregations?.sample.services.buckets.map((bucket) => { const topTransactionTypeBucket = - bucket.transactionType.buckets.find( - ({ key }) => - key === TRANSACTION_REQUEST || key === TRANSACTION_PAGE_LOAD + bucket.transactionType.buckets.find(({ key }) => + isDefaultTransactionType(key as string) ) ?? bucket.transactionType.buckets[0]; return { From 27d1cc7b310690b6816dbec873eb11b27271aaef Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Mon, 13 Feb 2023 12:27:44 +0100 Subject: [PATCH 122/203] [ML] Fix setting time bounds with `epoch_millis` formatting (#150867) --- .../change_point_detection_context.tsx | 7 ++++--- .../aiops/public/components/page_header/page_header.tsx | 8 +++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx index 9b9e414a71e6f..7c4980846a8d8 100644 --- a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx +++ b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx @@ -16,9 +16,10 @@ import React, { } from 'react'; import { type DataViewField } from '@kbn/data-views-plugin/public'; import { startWith } from 'rxjs'; -import type { Query, Filter } from '@kbn/es-query'; +import type { Filter, Query } from '@kbn/es-query'; import { usePageUrlState } from '@kbn/ml-url-state'; import { useTimefilter, useTimeRangeUpdates } from '@kbn/ml-date-picker'; +import moment from 'moment'; import { DEFAULT_AGG_FUNCTION } from './constants'; import { useSplitFieldCardinality } from './use_split_field_cardinality'; import { @@ -234,8 +235,8 @@ export const ChangePointDetectionContextProvider: FC = ({ children }) => { mergedQuery.bool!.filter.push({ range: { [dataView.timeFieldName!]: { - from: timeRange.from, - to: timeRange.to, + from: moment(timeRange.from).valueOf(), + to: moment(timeRange.to).valueOf(), }, }, }); diff --git a/x-pack/plugins/aiops/public/components/page_header/page_header.tsx b/x-pack/plugins/aiops/public/components/page_header/page_header.tsx index 627272bd2bd50..47a4e7aaf32e6 100644 --- a/x-pack/plugins/aiops/public/components/page_header/page_header.tsx +++ b/x-pack/plugins/aiops/public/components/page_header/page_header.tsx @@ -20,6 +20,7 @@ import { FROZEN_TIER_PREFERENCE, } from '@kbn/ml-date-picker'; +import moment from 'moment'; import { useDataSource } from '../../hooks/use_data_source'; import { AIOPS_FROZEN_TIER_PREFERENCE, @@ -51,7 +52,12 @@ export const PageHeader: FC = () => { const updateTimeState: FullTimeRangeSelectorProps['callback'] = useCallback( (update) => { - setGlobalState({ time: { from: update.start.string, to: update.end.string } }); + setGlobalState({ + time: { + from: moment(update.start.epoch).toISOString(), + to: moment(update.end.epoch).toISOString(), + }, + }); }, [setGlobalState] ); From 45f5f3d14c414d7873475e0e49b74919c62c64c3 Mon Sep 17 00:00:00 2001 From: Julia Bardi <90178898+juliaElastic@users.noreply.github.com> Date: Mon, 13 Feb 2023 12:58:04 +0100 Subject: [PATCH 123/203] [Fleet] fixed bug where installed beta integration was visible multiple times (#150979) ## Summary Fixes https://github.com/elastic/kibana/issues/150969 Filtering for only uploaded packages that are not in registry. This fixes of bug of linux integration showing up multiple times when the `/packages` call with `prerelease:false` and `prerelease:true` options are quickly following each other. To verify: - Navigate to Integrations, search `linux`. - Add linux integration to agent policy. - Repeat the same process again. - Navigate back to Integrations and search `linux`. - Only one Linux metrics integration card should be visible. image Uploaded integrations are still visible: image ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../fleet/server/services/epm/packages/get.test.ts | 6 +++--- x-pack/plugins/fleet/server/services/epm/packages/get.ts | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts index 52170f6c302fd..661784a99ced5 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.test.ts @@ -209,7 +209,7 @@ describe('When using EPM `get` services', () => { attributes: { name: 'elasticsearch', version: '0.0.1', - install_status: 'upload', + install_source: 'upload', }, }, ], @@ -221,16 +221,16 @@ describe('When using EPM `get` services', () => { }) ).resolves.toMatchObject([ { + id: 'elasticsearch', name: 'elasticsearch', version: '0.0.1', title: 'Elasticsearch', - status: 'upload', savedObject: { id: 'elasticsearch', attributes: { name: 'elasticsearch', version: '0.0.1', - install_status: 'upload', + install_source: 'upload', }, }, }, diff --git a/x-pack/plugins/fleet/server/services/epm/packages/get.ts b/x-pack/plugins/fleet/server/services/epm/packages/get.ts index 83db878ef5b83..7baddd428076b 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/get.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/get.ts @@ -74,9 +74,11 @@ export async function getPackages( // get the installed packages const packageSavedObjects = await getPackageSavedObjects(savedObjectsClient); - const packagesNotInRegistry = packageSavedObjects.saved_objects + const uploadedPackagesNotInRegistry = packageSavedObjects.saved_objects .filter((pkg) => !registryItems.some((item) => item.name === pkg.id)) - .map((pkg) => createInstallableFrom({ ...pkg.attributes, title: nameAsTitle(pkg.id) }, pkg)); + .map((pkg) => + createInstallableFrom({ ...pkg.attributes, title: nameAsTitle(pkg.id), id: pkg.id }, pkg) + ); const packageList = registryItems .map((item) => @@ -85,7 +87,7 @@ export async function getPackages( packageSavedObjects.saved_objects.find(({ id }) => id === item.name) ) ) - .concat(packagesNotInRegistry as Installable) + .concat(uploadedPackagesNotInRegistry as Installable) .sort(sortByName); if (!excludeInstallStatus) { From 2315285e37274d8aa724d517055a34272efbe3d7 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Mon, 13 Feb 2023 13:30:26 +0100 Subject: [PATCH 124/203] [Security Solutions] Fix link to ML Job is wrong when searching within ML Job Settings UI (#150881) issue: https://github.com/elastic/kibana/issues/150875 ## Summary Describe the bug: The link to an ML job is wrong when searching for a job. Steps to reproduce: 1. Open ML Job Settings UI 2. Type DNS in the search bar 3. Verify that the links have the wrong job Id. ### Before https://user-images.githubusercontent.com/1490444/218104808-94c93669-2de3-4fba-88c9-5f2b7ccaa391.mp4 ### After https://user-images.githubusercontent.com/1490444/218105267-b5aa118c-9d78-4648-9892-68afd5e2707f.mov --- .../analyze_dataset_in_ml_action.tsx | 31 +++++++++-------- .../plugins/ml/public/locator/use_ml_href.ts | 6 ++-- .../ml/links/create_explorer_link.tsx | 33 +++++++++++-------- .../ml_popover/jobs_table/jobs_table.tsx | 15 ++++++--- .../rules/ml_job_link/ml_job_link.tsx | 15 ++++++--- 5 files changed, 61 insertions(+), 39 deletions(-) diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx index 4d17b6ed9e8c5..6af0607580c4d 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx @@ -25,21 +25,26 @@ export const AnalyzeCategoryDatasetInMlAction: React.FunctionComponent<{ services: { ml, http, application }, } = useKibanaContextForPlugin(); - const viewAnomalyInMachineLearningLink = useMlHref(ml, http.basePath.get(), { - page: ML_PAGES.SINGLE_METRIC_VIEWER, - pageState: { - jobIds: [categorizationJobId], - timeRange: { - from: moment(timeRange.startTime).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), - to: moment(timeRange.endTime).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), - mode: 'absolute', - }, - entities: { - [partitionField]: dataset, - mlcategory: `${categoryId}`, + const viewAnomalyInMachineLearningLink = useMlHref( + ml, + http.basePath.get(), + { + page: ML_PAGES.SINGLE_METRIC_VIEWER, + pageState: { + jobIds: [categorizationJobId], + timeRange: { + from: moment(timeRange.startTime).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), + to: moment(timeRange.endTime).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), + mode: 'absolute', + }, + entities: { + [partitionField]: dataset, + mlcategory: `${categoryId}`, + }, }, }, - }); + [categorizationJobId] + ); const handleClick = useCallback( (e) => { diff --git a/x-pack/plugins/ml/public/locator/use_ml_href.ts b/x-pack/plugins/ml/public/locator/use_ml_href.ts index 59b34dffa7c13..1ed7321f3fd2f 100644 --- a/x-pack/plugins/ml/public/locator/use_ml_href.ts +++ b/x-pack/plugins/ml/public/locator/use_ml_href.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { DependencyList } from 'react'; import { MlPluginStart } from '..'; import { MlLocatorParams } from '../../common/types/locator'; @@ -15,10 +16,11 @@ import { MlLocatorParams } from '../../common/types/locator'; export const useMlHref = ( ml: MlPluginStart | undefined, basePath: string | undefined, - params: MlLocatorParams + params: MlLocatorParams, + dependencies?: DependencyList ) => { return ml && ml.locator - ? ml.locator!.useUrl(params) + ? ml.locator.useUrl(params, undefined, dependencies) : basePath !== undefined ? `${basePath}/app/ml/${params.page}` : ''; diff --git a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx index 9f7ed8a526e12..400d715754e92 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx @@ -28,22 +28,27 @@ export const ExplorerLink: React.FC = ({ services: { ml, http }, } = useKibana(); - const explorerUrl = useMlHref(ml, http.basePath.get(), { - page: 'explorer', - pageState: { - jobIds: [score.jobId], - timeRange: { - from: new Date(startDate).toISOString(), - to: new Date(endDate).toISOString(), - mode: 'absolute', - }, - refreshInterval: { - pause: true, - value: 0, - display: 'Off', + const explorerUrl = useMlHref( + ml, + http.basePath.get(), + { + page: 'explorer', + pageState: { + jobIds: [score.jobId], + timeRange: { + from: new Date(startDate).toISOString(), + to: new Date(endDate).toISOString(), + mode: 'absolute', + }, + refreshInterval: { + pause: true, + value: 0, + display: 'Off', + }, }, }, - }); + [score.jobId] + ); if (!explorerUrl) return null; diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx index f8c27cd71b1d2..8b3bbfa3f5aeb 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx @@ -47,12 +47,17 @@ const JobName = ({ id, name, description, basePath }: JobNameProps) => { services: { ml }, } = useKibana(); - const jobUrl = useMlHref(ml, basePath, { - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - pageState: { - jobId: id, + const jobUrl = useMlHref( + ml, + basePath, + { + page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + pageState: { + jobId: id, + }, }, - }); + [id] + ); return ( diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_link/ml_job_link.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_link/ml_job_link.tsx index 7680b5b72dff3..cbdddae858085 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_link/ml_job_link.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_link/ml_job_link.tsx @@ -25,12 +25,17 @@ const MlJobLinkComponent: React.FC = ({ jobId, jobName }) => { const { services: { http, ml }, } = useKibana(); - const jobUrl = useMlHref(ml, http.basePath.get(), { - page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, - pageState: { - jobId: [jobId], + const jobUrl = useMlHref( + ml, + http.basePath.get(), + { + page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, + pageState: { + jobId: [jobId], + }, }, - }); + [jobId] + ); return ( From a37376e72022c6c6e884ed94edbf63a99c70789d Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Mon, 13 Feb 2023 14:45:29 +0100 Subject: [PATCH 125/203] [Security Solution] Automates C18001 (#150973) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../cypress/e2e/cases/creation.cy.ts | 11 ++++++++++- .../security_solution/cypress/screens/overview.ts | 3 +++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/cypress/e2e/cases/creation.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/cases/creation.cy.ts index 0eaa67b3e1096..46bfd1f388ea6 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/cases/creation.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/cases/creation.cy.ts @@ -37,6 +37,8 @@ import { } from '../../screens/case_details'; import { TIMELINE_DESCRIPTION, TIMELINE_QUERY, TIMELINE_TITLE } from '../../screens/timeline'; +import { OVERVIEW_CASE_DESCRIPTION, OVERVIEW_CASE_NAME } from '../../screens/overview'; + import { goToCaseDetails, goToCreateNewCase } from '../../tasks/all_cases'; import { createTimeline } from '../../tasks/api_calls/timelines'; import { openCaseTimeline } from '../../tasks/case_details'; @@ -50,7 +52,7 @@ import { } from '../../tasks/create_new_case'; import { loginWithUser, visitWithoutDateRange } from '../../tasks/login'; -import { CASES_URL } from '../../urls/navigation'; +import { CASES_URL, OVERVIEW_URL } from '../../urls/navigation'; describe('Cases', () => { before(() => { @@ -120,5 +122,12 @@ describe('Cases', () => { cy.get(TIMELINE_TITLE).contains(this.mycase.timeline.title); cy.get(TIMELINE_DESCRIPTION).contains(this.mycase.timeline.description); cy.get(TIMELINE_QUERY).should('have.text', this.mycase.timeline.query); + + cy.visit(OVERVIEW_URL); + cy.get(OVERVIEW_CASE_NAME).should('have.text', this.mycase.name); + cy.get(OVERVIEW_CASE_DESCRIPTION).should( + 'have.text', + `${this.mycase.description} ${this.mycase.timeline.title}` + ); }); }); diff --git a/x-pack/plugins/security_solution/cypress/screens/overview.ts b/x-pack/plugins/security_solution/cypress/screens/overview.ts index 12de337a51aa3..e7357adc2353d 100644 --- a/x-pack/plugins/security_solution/cypress/screens/overview.ts +++ b/x-pack/plugins/security_solution/cypress/screens/overview.ts @@ -140,6 +140,9 @@ export const NETWORK_STATS = [ STAT_TLS, ]; +export const OVERVIEW_CASE_NAME = '[data-test-subj="case-details-link"]'; +export const OVERVIEW_CASE_DESCRIPTION = '.euiText.euiMarkdownFormat'; + export const OVERVIEW_HOST_STATS = '[data-test-subj="overview-hosts-stats"]'; export const OVERVIEW_NETWORK_STATS = '[data-test-subj="overview-network-stats"]'; From 39197628d2be02fb9a97666993c0514c1950b382 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Mon, 13 Feb 2023 09:14:40 -0500 Subject: [PATCH 126/203] [Security Solution] Update error codes for reporting es connection errors (#150792) ## Summary This PR fixes a bug where we weren't checking the uppercase version of input statuses. In addition, it adds another error code to check for Endpoint when it cannot ship data to ES. We also needed to check for `DEGRADED` status in addition to `FAILED` Mac OS full disk access reporting image ES connection errors: ![image](https://user-images.githubusercontent.com/56395104/217945339-1bac8935-6453-45b6-ad47-d1d546a7dfc2.png) Response from Agent/Endpoint image ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../plugins/fleet/common/constants/agent.ts | 14 +++++------ .../agent_details_integrations.tsx | 4 ++- .../common/endpoint/constants.ts | 1 + .../data_generators/fleet_agent_generator.ts | 2 +- .../package_action.formatter.test.ts | 25 +++++++++++++++++-- .../package_action_formatter.ts | 7 ++++-- .../endpoint_generic_errors_list.tsx | 2 +- 7 files changed, 41 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/fleet/common/constants/agent.ts b/x-pack/plugins/fleet/common/constants/agent.ts index 6d4133c32c6c7..d05dd66bb096b 100644 --- a/x-pack/plugins/fleet/common/constants/agent.ts +++ b/x-pack/plugins/fleet/common/constants/agent.ts @@ -27,11 +27,11 @@ export const AGENT_ACTIONS_INDEX = '.fleet-actions'; export const AGENT_ACTIONS_RESULTS_INDEX = '.fleet-actions-results'; export const FleetServerAgentComponentStatuses = [ - 'starting', - 'configuring', - 'healthy', - 'degraded', - 'failed', - 'stopping', - 'stopped', + 'STARTING', + 'CONFIGURING', + 'HEALTHY', + 'DEGRADED', + 'FAILED', + 'STOPPING', + 'STOPPED', ] as const; 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 16504516c72ab..9283416a111a8 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 @@ -131,7 +131,9 @@ export const AgentDetailsIntegration: React.FunctionComponent<{ }); filteredPackageComponents.forEach((component) => { - packageErrorUnits.push(...filter(component.units, { status: 'failed' })); + packageErrorUnits.push( + ...filter(component.units, (u) => u.status === 'DEGRADED' || u.status === 'FAILED') + ); }); return packageErrorUnits; }, [agent.components, packagePolicy]); diff --git a/x-pack/plugins/security_solution/common/endpoint/constants.ts b/x-pack/plugins/security_solution/common/endpoint/constants.ts index d005f449d76a3..175f1cfdf14e4 100644 --- a/x-pack/plugins/security_solution/common/endpoint/constants.ts +++ b/x-pack/plugins/security_solution/common/endpoint/constants.ts @@ -94,6 +94,7 @@ export const ENDPOINT_DEFAULT_PAGE_SIZE = 10; export const ENDPOINT_ERROR_CODES: Record = { ES_CONNECTION_ERROR: -272, + OUTPUT_SERVER_ERROR: -273, }; export const ENDPOINT_FIELDS_SEARCH_STRATEGY = 'endpointFields'; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts index 39e7efc47c455..ea5c377102b17 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts @@ -88,7 +88,7 @@ export class FleetAgentGenerator extends BaseDataGenerator { FleetServerAgentComponentStatuses ); const componentInputPayload = - componentStatus === 'failed' + componentStatus === 'FAILED' ? { error: { code: ENDPOINT_ERROR_CODES.ES_CONNECTION_ERROR, diff --git a/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action.formatter.test.ts b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action.formatter.test.ts index dc5c443e15e2e..2dee21fcc89da 100644 --- a/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action.formatter.test.ts +++ b/x-pack/plugins/security_solution/public/management/components/package_action_item/package_action.formatter.test.ts @@ -15,7 +15,7 @@ describe('PackageActionFormatter', () => { const unit: FleetServerAgentComponentUnit = { id: 'test-id', type: 'input', - status: 'failed', + status: 'FAILED', message: 'test message', payload: { error: { @@ -32,11 +32,32 @@ describe('PackageActionFormatter', () => { expect(formatter.linkUrl).toBe(docLinks.es_connection); }); + it('correctly formats output connection error', () => { + const unit: FleetServerAgentComponentUnit = { + id: 'test-id', + type: 'input', + status: 'DEGRADED', + message: 'test message', + payload: { + error: { + code: ENDPOINT_ERROR_CODES.OUTPUT_SERVER_ERROR, + message: 'an error message', + }, + }, + }; + const docLinks = { es_connection: 'somedoclink' }; + const formatter = new PackageActionFormatter(unit, docLinks); + expect(formatter.key).toBe('es_connection'); + expect(formatter.title).toBe(titles.get('es_connection')); + expect(formatter.description).toBe(descriptions.get('es_connection')); + expect(formatter.linkUrl).toBe(docLinks.es_connection); + }); + it('correct formats generic error', () => { const unit: FleetServerAgentComponentUnit = { id: 'test-id', type: 'input', - status: 'failed', + status: 'FAILED', message: 'test message', }; const docLinks = { es_connection: 'somedoclink' }; 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 9af6983ecfcdb..f611f3d78f1c1 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 @@ -101,9 +101,12 @@ export class PackageActionFormatter { code: number, status: FleetServerAgentComponentStatus ): PackageActions { - if (code === ENDPOINT_ERROR_CODES.ES_CONNECTION_ERROR) { + if ( + code === ENDPOINT_ERROR_CODES.ES_CONNECTION_ERROR || + code === ENDPOINT_ERROR_CODES.OUTPUT_SERVER_ERROR + ) { return 'es_connection'; - } else if (status === 'failed') { + } else if (status === 'FAILED' || status === 'DEGRADED') { return 'policy_failure'; } else { throw new Error(`Invalid error code ${code}`); 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 index babb4c78af147..e3902e965632a 100644 --- 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 @@ -23,7 +23,7 @@ export const EndpointGenericErrorsList = memo( const globalEndpointErrors = useMemo(() => { const errors: PackageActionFormatter[] = []; packageErrors.forEach((unit) => { - if (unit.status === 'failed') { + if (unit.status === 'FAILED' || unit.status === 'DEGRADED') { errors.push( new PackageActionFormatter( unit, From 2749e95fe0a5f0d1617129765eb3b84ea0cec097 Mon Sep 17 00:00:00 2001 From: "Devin W. Hurley" Date: Mon, 13 Feb 2023 09:29:58 -0500 Subject: [PATCH 127/203] [Security Solution] [Exceptions] fixes download from list details page (#150933) ## Summary Fixes: https://github.com/elastic/kibana/issues/148139 When exporting a shared exception list from that lists' detailed view, the exported file would not have the `.ndjson` extension appended to it. I think we should update this to be a single hook used between the two views. --- .../public/exceptions/hooks/use_list_detail_view/index.ts | 5 +++++ .../public/exceptions/pages/list_detail_view/index.tsx | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts index 949854d78ae65..3359ccb760b05 100644 --- a/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts +++ b/x-pack/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts @@ -190,6 +190,10 @@ export const useListDetailsView = (exceptionListId: string) => { [list, exportExceptionList, handleErrorStatus, toasts] ); + const handleOnDownload = useCallback(() => { + setExportedList(undefined); + }, []); + // #region DeleteList const handleDeleteSuccess = useCallback( @@ -366,6 +370,7 @@ export const useListDetailsView = (exceptionListId: string) => { canUserEditList, linkedRules, exportedList, + handleOnDownload, viewerStatus, showManageRulesFlyout, headerBackOptions, diff --git a/x-pack/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx b/x-pack/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx index 0be51bf851ba1..fc09a603b2e13 100644 --- a/x-pack/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx @@ -39,6 +39,7 @@ export const ListsDetailViewComponent: FC = () => { listId, linkedRules, exportedList, + handleOnDownload, viewerStatus, listName, listDescription, @@ -91,7 +92,7 @@ export const ListsDetailViewComponent: FC = () => { onManageRules={onManageRules} /> - + { canUserEditList, disableManageButton, exportedList, + handleOnDownload, headerBackOptions, invalidListId, isLoading, From 4f1f2a84fdf3421d6b56aac82274dee2e881d376 Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Mon, 13 Feb 2023 16:00:20 +0100 Subject: [PATCH 128/203] [Security Solution] Invalidate prebuilt rules status after package upgrade or installation (#150292) **Resolves: https://github.com/elastic/kibana/issues/150306** ## Summary Fixes the Load Prebuilt rules button not visible when users visit the rules management page for the first time (no prebuilt detection rules package installed). ## Steps to test 1. Ensure that the detection engine package is not installed: 2. Navigate to the rules management page. ### Previously The "Load Elastic Prebuilt Rules" button is not visible, and users cannot install prebuilt rules. ### With the fix Users now see loading animation, indicating that the package installation happens in the background. Once the package installation finishes, users see the Load Prebuilt rules button appear. https://user-images.githubusercontent.com/1938181/217585144-879fe288-0ede-4e01-b585-6aced1d89379.mov --- .../public/app/home/index.tsx | 2 +- .../hooks/use_upgrade_security_packages.ts | 113 ------------------ .../rule_management/api/api.ts | 61 ++++++++++ ...se_bulk_install_fleet_packages_mutation.ts | 44 +++++++ .../use_install_fleet_package_mutation.ts | 41 +++++++ .../logic/use_install_pre_packaged_rules.ts | 11 +- .../use_upgrade_secuirty_packages.test.tsx | 109 +++++++---------- .../logic/use_upgrade_security_packages.ts | 95 +++++++++++++++ .../components/rules_table/rules_tables.tsx | 4 +- .../load_prepackaged_rules.tsx | 10 +- 10 files changed, 304 insertions(+), 186 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/common/hooks/use_upgrade_security_packages.ts create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_bulk_install_fleet_packages_mutation.ts create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_install_fleet_package_mutation.ts rename x-pack/plugins/security_solution/public/{common/hooks => detection_engine/rule_management/logic}/use_upgrade_secuirty_packages.test.tsx (57%) create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_upgrade_security_packages.ts diff --git a/x-pack/plugins/security_solution/public/app/home/index.tsx b/x-pack/plugins/security_solution/public/app/home/index.tsx index 5aecd3cdc62ba..d74eb3eed5af7 100644 --- a/x-pack/plugins/security_solution/public/app/home/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/index.tsx @@ -18,7 +18,6 @@ import { getScopeFromPath, useSourcererDataView, } from '../../common/containers/sourcerer'; -import { useUpgradeSecurityPackages } from '../../common/hooks/use_upgrade_security_packages'; import { GlobalHeader } from './global_header'; import { ConsoleManager } from '../../management/components/console/components/console_manager'; @@ -26,6 +25,7 @@ import { TourContextProvider } from '../../common/components/guided_onboarding_t import { useUrlState } from '../../common/hooks/use_url_state'; import { useUpdateBrowserTitle } from '../../common/hooks/use_update_browser_title'; +import { useUpgradeSecurityPackages } from '../../detection_engine/rule_management/logic/use_upgrade_security_packages'; interface HomePageProps { children: React.ReactNode; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_upgrade_security_packages.ts b/x-pack/plugins/security_solution/public/common/hooks/use_upgrade_security_packages.ts deleted file mode 100644 index 3ffb3ca149b20..0000000000000 --- a/x-pack/plugins/security_solution/public/common/hooks/use_upgrade_security_packages.ts +++ /dev/null @@ -1,113 +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 { useEffect } from 'react'; -import type { HttpFetchOptions, HttpStart } from '@kbn/core/public'; -import type { BulkInstallPackagesResponse } from '@kbn/fleet-plugin/common'; -import { epmRouteService } from '@kbn/fleet-plugin/common'; -import type { InstallPackageResponse } from '@kbn/fleet-plugin/common/types'; -import { KibanaServices, useKibana } from '../lib/kibana'; -import { useUserPrivileges } from '../components/user_privileges'; -import { PREBUILT_RULES_PACKAGE_NAME } from '../../../common/detection_engine/constants'; - -/** - * Requests that the endpoint and security_detection_engine package be upgraded to the latest version - * - * @param http an http client for sending the request - * @param options an object containing options for the request - * @param prebuiltRulesPackageVersion specific version of the prebuilt rules package to install - */ -const sendUpgradeSecurityPackages = async ( - http: HttpStart, - options: HttpFetchOptions = {}, - prebuiltRulesPackageVersion?: string -): Promise => { - const packages = ['endpoint', PREBUILT_RULES_PACKAGE_NAME]; - const requests: Array> = []; - - // If `prebuiltRulesPackageVersion` is provided, try to install that version - // Must be done as two separate requests as bulk API doesn't support versions - if (prebuiltRulesPackageVersion != null) { - packages.splice(packages.indexOf(PREBUILT_RULES_PACKAGE_NAME), 1); - requests.push( - http.post( - epmRouteService.getInstallPath(PREBUILT_RULES_PACKAGE_NAME, prebuiltRulesPackageVersion), - { - ...options, - body: JSON.stringify({ - force: true, - }), - } - ) - ); - } - - // Note: if `prerelease:true` option is provided, endpoint package will also be installed as prerelease - requests.push( - http.post(epmRouteService.getBulkInstallPath(), { - ...options, - body: JSON.stringify({ - packages, - }), - }) - ); - - await Promise.allSettled(requests); -}; - -export const useUpgradeSecurityPackages = () => { - const context = useKibana(); - const canAccessFleet = useUserPrivileges().endpointPrivileges.canAccessFleet; - - useEffect(() => { - const abortController = new AbortController(); - - // cancel any ongoing requests - const abortRequests = () => { - abortController.abort(); - }; - - if (canAccessFleet) { - const signal = abortController.signal; - - (async () => { - try { - // Make sure fleet is initialized first - await context.services.fleet?.isInitialized(); - - // Always install the latest package if in dev env or snapshot build - const isPrerelease = - KibanaServices.getKibanaVersion().includes('-SNAPSHOT') || - KibanaServices.getKibanaBranch() === 'main'; - - // ignore the response for now since we aren't notifying the user - // Note: response would be Promise.allSettled, so must iterate all responses for errors and throw manually - await sendUpgradeSecurityPackages( - context.services.http, - { - query: { - prerelease: isPrerelease, - }, - signal, - }, - KibanaServices.getPrebuiltRulesPackageVersion() - ); - } catch (error) { - // Ignore Errors, since this should not hinder the user's ability to use the UI - - // log to console, except if the error occurred due to aborting a request - if (!abortController.signal.aborted) { - // eslint-disable-next-line no-console - console.error(error); - } - } - })(); - - return abortRequests; - } - }, [canAccessFleet, context.services.fleet, context.services.http]); -}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts index 87334a121c993..386dbf3c7b525 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/api.ts @@ -10,6 +10,9 @@ import type { ExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; +import type { BulkInstallPackagesResponse } from '@kbn/fleet-plugin/common'; +import { epmRouteService } from '@kbn/fleet-plugin/common'; +import type { InstallPackageResponse } from '@kbn/fleet-plugin/common/types'; import type { RuleManagementFiltersResponse } from '../../../../common/detection_engine/rule_management/api/rules/filters/response_schema'; import { RULE_MANAGEMENT_FILTERS_URL } from '../../../../common/detection_engine/rule_management/api/urls'; import type { BulkActionsDryRunErrCode } from '../../../../common/constants'; @@ -481,3 +484,61 @@ export const addRuleExceptions = async ({ signal, } ); + +export interface InstallFleetPackageProps { + packageName: string; + packageVersion: string; + prerelease?: boolean; + force?: boolean; +} + +/** + * Install a Fleet package from the registry + * + * @param packageName Name of the package to install + * @param packageVersion Version of the package to install + * @param prerelease Whether to install a prerelease version of the package + * @param force Whether to force install the package. If false, the package will only be installed if it is not already installed + * + * @returns The response from the Fleet API + */ +export const installFleetPackage = ({ + packageName, + packageVersion, + prerelease = false, + force = true, +}: InstallFleetPackageProps): Promise => { + return KibanaServices.get().http.post( + epmRouteService.getInstallPath(packageName, packageVersion), + { + query: { prerelease }, + body: JSON.stringify({ force }), + } + ); +}; + +export interface BulkInstallFleetPackagesProps { + packages: string[]; + prerelease?: boolean; +} + +/** + * Install multiple Fleet packages from the registry + * + * @param packages Array of package names to install + * @param prerelease Whether to install prerelease versions of the packages + * + * @returns The response from the Fleet API + */ +export const bulkInstallFleetPackages = ({ + packages, + prerelease = false, +}: BulkInstallFleetPackagesProps): Promise => { + return KibanaServices.get().http.post( + epmRouteService.getBulkInstallPath(), + { + query: { prerelease }, + body: JSON.stringify({ packages }), + } + ); +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_bulk_install_fleet_packages_mutation.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_bulk_install_fleet_packages_mutation.ts new file mode 100644 index 0000000000000..adbcec981ca3c --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_bulk_install_fleet_packages_mutation.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 { EPM_API_ROUTES } from '@kbn/fleet-plugin/common'; +import type { BulkInstallPackagesResponse } from '@kbn/fleet-plugin/common/types'; +import type { UseMutationOptions } from '@tanstack/react-query'; +import { useMutation } from '@tanstack/react-query'; +import { PREBUILT_RULES_PACKAGE_NAME } from '../../../../../common/detection_engine/constants'; +import type { BulkInstallFleetPackagesProps } from '../api'; +import { bulkInstallFleetPackages } from '../api'; +import { useInvalidateFetchPrebuiltRulesStatusQuery } from './use_fetch_prebuilt_rules_status_query'; + +export const BULK_INSTALL_FLEET_PACKAGES_MUTATION_KEY = [ + 'POST', + EPM_API_ROUTES.BULK_INSTALL_PATTERN, +]; + +export const useBulkInstallFleetPackagesMutation = ( + options?: UseMutationOptions +) => { + const invalidatePrePackagedRulesStatus = useInvalidateFetchPrebuiltRulesStatusQuery(); + + return useMutation((props: BulkInstallFleetPackagesProps) => bulkInstallFleetPackages(props), { + ...options, + mutationKey: BULK_INSTALL_FLEET_PACKAGES_MUTATION_KEY, + onSettled: (...args) => { + const response = args[0]; + const rulesPackage = response?.items.find( + (item) => item.name === PREBUILT_RULES_PACKAGE_NAME + ); + if (rulesPackage && 'result' in rulesPackage && rulesPackage.result.status === 'installed') { + // The rules package was installed/updated, so invalidate the pre-packaged rules status query + invalidatePrePackagedRulesStatus(); + } + + if (options?.onSettled) { + options.onSettled(...args); + } + }, + }); +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_install_fleet_package_mutation.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_install_fleet_package_mutation.ts new file mode 100644 index 0000000000000..0e6927e1745dd --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/api/hooks/use_install_fleet_package_mutation.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 { EPM_API_ROUTES } from '@kbn/fleet-plugin/common'; +import type { InstallPackageResponse } from '@kbn/fleet-plugin/common/types'; +import type { UseMutationOptions } from '@tanstack/react-query'; +import { useMutation } from '@tanstack/react-query'; +import { PREBUILT_RULES_PACKAGE_NAME } from '../../../../../common/detection_engine/constants'; +import type { InstallFleetPackageProps } from '../api'; +import { installFleetPackage } from '../api'; +import { useInvalidateFetchPrebuiltRulesStatusQuery } from './use_fetch_prebuilt_rules_status_query'; + +export const INSTALL_FLEET_PACKAGE_MUTATION_KEY = [ + 'POST', + EPM_API_ROUTES.INSTALL_FROM_REGISTRY_PATTERN, +]; + +export const useInstallFleetPackageMutation = ( + options?: UseMutationOptions +) => { + const invalidatePrePackagedRulesStatus = useInvalidateFetchPrebuiltRulesStatusQuery(); + + return useMutation((props: InstallFleetPackageProps) => installFleetPackage(props), { + ...options, + mutationKey: INSTALL_FLEET_PACKAGE_MUTATION_KEY, + onSettled: (...args) => { + const { packageName } = args[2]; + if (packageName === PREBUILT_RULES_PACKAGE_NAME) { + // Invalidate the pre-packaged rules status query as there might be new rules to install + invalidatePrePackagedRulesStatus(); + } + + if (options?.onSettled) { + options.onSettled(...args); + } + }, + }); +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_install_pre_packaged_rules.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_install_pre_packaged_rules.ts index 21ea298986598..b7fa307c0fedc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_install_pre_packaged_rules.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_install_pre_packaged_rules.ts @@ -4,8 +4,12 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { useIsMutating } from '@tanstack/react-query'; import { useAppToasts } from '../../../common/hooks/use_app_toasts'; -import { useCreatePrebuiltRulesMutation } from '../api/hooks/use_create_prebuilt_rules_mutation'; +import { + CREATE_PREBUILT_RULES_MUTATION_KEY, + useCreatePrebuiltRulesMutation, +} from '../api/hooks/use_create_prebuilt_rules_mutation'; import * as i18n from './translations'; export const useInstallPrePackagedRules = () => { @@ -21,6 +25,11 @@ export const useInstallPrePackagedRules = () => { }); }; +export const useIsInstallingPrePackagedRules = () => { + const mutationsCount = useIsMutating(CREATE_PREBUILT_RULES_MUTATION_KEY); + return mutationsCount > 0; +}; + const getSuccessToastMessage = (result: { rules_installed: number; rules_updated: number; diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_upgrade_secuirty_packages.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_upgrade_secuirty_packages.test.tsx similarity index 57% rename from x-pack/plugins/security_solution/public/common/hooks/use_upgrade_secuirty_packages.test.tsx rename to x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_upgrade_secuirty_packages.test.tsx index 0352dd03bbcff..dd01465b8875a 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_upgrade_secuirty_packages.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_upgrade_secuirty_packages.test.tsx @@ -5,14 +5,13 @@ * 2.0. */ -import React, { memo } from 'react'; -import { KibanaServices, useKibana } from '../lib/kibana'; -import type { RenderHookResult } from '@testing-library/react-hooks'; -import { renderHook as _renderHook } from '@testing-library/react-hooks'; -import { useUpgradeSecurityPackages } from './use_upgrade_security_packages'; import { epmRouteService } from '@kbn/fleet-plugin/common'; +import { renderHook } from '@testing-library/react-hooks'; +import { useKibana, KibanaServices } from '../../../common/lib/kibana'; +import { TestProviders } from '../../../common/mock'; +import { useUpgradeSecurityPackages } from './use_upgrade_security_packages'; -jest.mock('../components/user_privileges', () => { +jest.mock('../../../common/components/user_privileges', () => { return { useUserPrivileges: jest.fn().mockReturnValue({ endpointPrivileges: { @@ -21,48 +20,30 @@ jest.mock('../components/user_privileges', () => { }), }; }); -jest.mock('../lib/kibana'); +jest.mock('../../../common/lib/kibana'); -describe('When using the `useUpgradeSecurityPackages()` hook', () => { - const mockGetPrebuiltRulesPackageVersion = - KibanaServices.getPrebuiltRulesPackageVersion as jest.Mock; - const mockGetKibanaVersion = KibanaServices.getKibanaVersion as jest.Mock; - const mockGetKibanaBranch = KibanaServices.getKibanaBranch as jest.Mock; - let renderResult: RenderHookResult; - let renderHook: () => RenderHookResult; - let kibana: ReturnType; - - // eslint-disable-next-line react/display-name - const Wrapper = memo(({ children }) => { - kibana = useKibana(); - return <>{children}; - }); +const mockGetPrebuiltRulesPackageVersion = + KibanaServices.getPrebuiltRulesPackageVersion as jest.Mock; +const mockGetKibanaVersion = KibanaServices.getKibanaVersion as jest.Mock; +const mockGetKibanaBranch = KibanaServices.getKibanaBranch as jest.Mock; +const useKibanaMock = useKibana as jest.MockedFunction; +describe('When using the `useUpgradeSecurityPackages()` hook', () => { beforeEach(() => { - renderHook = () => { - renderResult = _renderHook(() => useUpgradeSecurityPackages(), { wrapper: Wrapper }); - return renderResult; - }; - }); - - afterEach(() => { jest.clearAllMocks(); - if (renderResult) { - renderResult.unmount(); - } }); it('should call fleet setup first via `isInitialized()` and then send upgrade request', async () => { - renderHook(); + const { waitFor } = renderHook(() => useUpgradeSecurityPackages(), { + wrapper: TestProviders, + }); - expect(kibana.services.fleet?.isInitialized).toHaveBeenCalled(); - expect(kibana.services.http.post).not.toHaveBeenCalled(); + expect(useKibanaMock().services.fleet?.isInitialized).toHaveBeenCalled(); + expect(useKibanaMock().services.http.post).not.toHaveBeenCalled(); - await renderResult.waitFor( - () => (kibana.services.http.post as jest.Mock).mock.calls.length > 0 - ); + await waitFor(() => (useKibanaMock().services.http.post as jest.Mock).mock.calls.length > 0); - expect(kibana.services.http.post).toHaveBeenCalledWith( + expect(useKibanaMock().services.http.post).toHaveBeenCalledWith( `${epmRouteService.getBulkInstallPath()}`, expect.objectContaining({ body: '{"packages":["endpoint","security_detection_engine"]}', @@ -74,13 +55,13 @@ describe('When using the `useUpgradeSecurityPackages()` hook', () => { mockGetKibanaVersion.mockReturnValue('8.0.0'); mockGetKibanaBranch.mockReturnValue('release'); - renderHook(); + const { waitFor } = renderHook(() => useUpgradeSecurityPackages(), { + wrapper: TestProviders, + }); - await renderResult.waitFor( - () => (kibana.services.http.post as jest.Mock).mock.calls.length > 0 - ); + await waitFor(() => (useKibanaMock().services.http.post as jest.Mock).mock.calls.length > 0); - expect(kibana.services.http.post).toHaveBeenCalledWith( + expect(useKibanaMock().services.http.post).toHaveBeenCalledWith( `${epmRouteService.getBulkInstallPath()}`, expect.objectContaining({ body: '{"packages":["endpoint","security_detection_engine"]}', @@ -93,13 +74,13 @@ describe('When using the `useUpgradeSecurityPackages()` hook', () => { mockGetKibanaVersion.mockReturnValue('8.0.0-SNAPSHOT'); mockGetKibanaBranch.mockReturnValue('main'); - renderHook(); + const { waitFor } = renderHook(() => useUpgradeSecurityPackages(), { + wrapper: TestProviders, + }); - await renderResult.waitFor( - () => (kibana.services.http.post as jest.Mock).mock.calls.length > 0 - ); + await waitFor(() => (useKibanaMock().services.http.post as jest.Mock).mock.calls.length > 0); - expect(kibana.services.http.post).toHaveBeenCalledWith( + expect(useKibanaMock().services.http.post).toHaveBeenCalledWith( `${epmRouteService.getBulkInstallPath()}`, expect.objectContaining({ body: '{"packages":["endpoint","security_detection_engine"]}', @@ -112,13 +93,13 @@ describe('When using the `useUpgradeSecurityPackages()` hook', () => { mockGetKibanaVersion.mockReturnValue('8.0.0-SNAPSHOT'); mockGetKibanaBranch.mockReturnValue('release'); - renderHook(); + const { waitFor } = renderHook(() => useUpgradeSecurityPackages(), { + wrapper: TestProviders, + }); - await renderResult.waitFor( - () => (kibana.services.http.post as jest.Mock).mock.calls.length > 0 - ); + await waitFor(() => (useKibanaMock().services.http.post as jest.Mock).mock.calls.length > 0); - expect(kibana.services.http.post).toHaveBeenCalledWith( + expect(useKibanaMock().services.http.post).toHaveBeenCalledWith( `${epmRouteService.getBulkInstallPath()}`, expect.objectContaining({ body: '{"packages":["endpoint","security_detection_engine"]}', @@ -131,13 +112,13 @@ describe('When using the `useUpgradeSecurityPackages()` hook', () => { mockGetKibanaVersion.mockReturnValue('8.0.0'); mockGetKibanaBranch.mockReturnValue('main'); - renderHook(); + const { waitFor } = renderHook(() => useUpgradeSecurityPackages(), { + wrapper: TestProviders, + }); - await renderResult.waitFor( - () => (kibana.services.http.post as jest.Mock).mock.calls.length > 0 - ); + await waitFor(() => (useKibanaMock().services.http.post as jest.Mock).mock.calls.length > 0); - expect(kibana.services.http.post).toHaveBeenCalledWith( + expect(useKibanaMock().services.http.post).toHaveBeenCalledWith( `${epmRouteService.getBulkInstallPath()}`, expect.objectContaining({ body: '{"packages":["endpoint","security_detection_engine"]}', @@ -149,18 +130,18 @@ describe('When using the `useUpgradeSecurityPackages()` hook', () => { it('should send separate upgrade requests if prebuiltRulesPackageVersion is provided', async () => { mockGetPrebuiltRulesPackageVersion.mockReturnValue('8.2.1'); - renderHook(); + const { waitFor } = renderHook(() => useUpgradeSecurityPackages(), { + wrapper: TestProviders, + }); - await renderResult.waitFor( - () => (kibana.services.http.post as jest.Mock).mock.calls.length > 0 - ); + await waitFor(() => (useKibanaMock().services.http.post as jest.Mock).mock.calls.length > 0); - expect(kibana.services.http.post).toHaveBeenNthCalledWith( + expect(useKibanaMock().services.http.post).toHaveBeenNthCalledWith( 1, `${epmRouteService.getInstallPath('security_detection_engine', '8.2.1')}`, expect.objectContaining({ query: { prerelease: true } }) ); - expect(kibana.services.http.post).toHaveBeenNthCalledWith( + expect(useKibanaMock().services.http.post).toHaveBeenNthCalledWith( 2, `${epmRouteService.getBulkInstallPath()}`, expect.objectContaining({ diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_upgrade_security_packages.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_upgrade_security_packages.ts new file mode 100644 index 0000000000000..296d041002f21 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/logic/use_upgrade_security_packages.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useIsMutating } from '@tanstack/react-query'; +import { useEffect } from 'react'; +import { PREBUILT_RULES_PACKAGE_NAME } from '../../../../common/detection_engine/constants'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; +import { KibanaServices, useKibana } from '../../../common/lib/kibana'; +import type { BulkInstallFleetPackagesProps, InstallFleetPackageProps } from '../api/api'; +import { + BULK_INSTALL_FLEET_PACKAGES_MUTATION_KEY, + useBulkInstallFleetPackagesMutation, +} from '../api/hooks/use_bulk_install_fleet_packages_mutation'; +import { + INSTALL_FLEET_PACKAGE_MUTATION_KEY, + useInstallFleetPackageMutation, +} from '../api/hooks/use_install_fleet_package_mutation'; + +/** + * Install or upgrade the security packages (endpoint and prebuilt rules) + */ +export const useUpgradeSecurityPackages = () => { + const context = useKibana(); + const canAccessFleet = useUserPrivileges().endpointPrivileges.canAccessFleet; + const { mutate: bulkInstallFleetPackages } = useBulkInstallFleetPackagesMutation(); + const { mutate: installFleetPackage } = useInstallFleetPackageMutation(); + + useEffect(() => { + if (!canAccessFleet) { + return; + } + + (async () => { + // Make sure fleet is initialized first + await context.services.fleet?.isInitialized(); + + // Always install the latest package if in dev env or snapshot build + const prerelease = + KibanaServices.getKibanaVersion().includes('-SNAPSHOT') || + KibanaServices.getKibanaBranch() === 'main'; + + const prebuiltRulesPackageVersion = KibanaServices.getPrebuiltRulesPackageVersion(); + // ignore the response for now since we aren't notifying the user + const packages = ['endpoint', PREBUILT_RULES_PACKAGE_NAME]; + + // If `prebuiltRulesPackageVersion` is provided, try to install that version + // Must be done as two separate requests as bulk API doesn't support versions + if (prebuiltRulesPackageVersion != null) { + installFleetPackage({ + packageName: PREBUILT_RULES_PACKAGE_NAME, + packageVersion: prebuiltRulesPackageVersion, + prerelease, + force: true, + }); + packages.splice(packages.indexOf(PREBUILT_RULES_PACKAGE_NAME), 1); + } + + // Note: if `prerelease:true` option is provided, endpoint package will also be installed as prerelease + bulkInstallFleetPackages({ + packages, + prerelease, + }); + })(); + }, [bulkInstallFleetPackages, canAccessFleet, context.services.fleet, installFleetPackage]); +}; + +/** + * @returns true if the security packages are being installed or upgraded + */ +export const useIsUpgradingSecurityPackages = () => { + const isInstallingPackages = useIsMutating({ + predicate: ({ options }) => { + const { mutationKey, variables } = options; + + // The mutation is bulk Fleet packages installation. Check if the packages include the prebuilt rules package + if (mutationKey === BULK_INSTALL_FLEET_PACKAGES_MUTATION_KEY) { + return (variables as BulkInstallFleetPackagesProps).packages.includes( + PREBUILT_RULES_PACKAGE_NAME + ); + } + + // The mutation is single Fleet package installation. Check if the package is the prebuilt rules package + if (mutationKey === INSTALL_FLEET_PACKAGE_MUTATION_KEY) { + return (variables as InstallFleetPackageProps).packageName === PREBUILT_RULES_PACKAGE_NAME; + } + return false; + }, + }); + + return isInstallingPackages > 0; +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx index bbe5659e7481b..31ae3af97f0ae 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_tables.tsx @@ -40,6 +40,7 @@ import { useStartMlJobs } from '../../../rule_management/logic/use_start_ml_jobs import { RULES_TABLE_PAGE_SIZE_OPTIONS } from './constants'; import { useRuleManagementFilters } from '../../../rule_management/logic/use_rule_management_filters'; import type { FindRulesSortField } from '../../../../../common/detection_engine/rule_management'; +import { useIsUpgradingSecurityPackages } from '../../../rule_management/logic/use_upgrade_security_packages'; const INITIAL_SORT_FIELD = 'enabled'; @@ -63,6 +64,7 @@ const NO_ITEMS_MESSAGE = ( export const RulesTables = React.memo(({ selectedTab }) => { const [{ canUserCRUD }] = useUserData(); const hasPermissions = hasUserCRUDPermission(canUserCRUD); + const isUpgradingSecurityPackages = useIsUpgradingSecurityPackages(); const tableRef = useRef(null); const rulesTableContext = useRulesTableContext(); @@ -227,7 +229,7 @@ export const RulesTables = React.memo(({ selectedTab }) => { } : { 'data-test-subj': 'monitoring-table', columns: monitoringColumns }; - const shouldShowLinearProgress = isFetched && isRefetching; + const shouldShowLinearProgress = (isFetched && isRefetching) || isUpgradingSecurityPackages; const shouldShowLoadingOverlay = (!isFetched && isRefetching) || isPreflightInProgress; return ( diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/pre_packaged_rules/load_prepackaged_rules.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/pre_packaged_rules/load_prepackaged_rules.tsx index e5d05d7e7fbb0..9ec37ecfcb7c0 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/pre_packaged_rules/load_prepackaged_rules.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/pre_packaged_rules/load_prepackaged_rules.tsx @@ -11,6 +11,7 @@ import { useBoolState } from '../../../../common/hooks/use_bool_state'; import { RULES_TABLE_ACTIONS } from '../../../../common/lib/apm/user_actions'; import { useStartTransaction } from '../../../../common/lib/apm/use_start_transaction'; import { useCreatePrePackagedRules } from '../../../../detection_engine/rule_management/logic/use_create_pre_packaged_rules'; +import { useIsInstallingPrePackagedRules } from '../../../../detection_engine/rule_management/logic/use_install_pre_packaged_rules'; import { usePrePackagedRulesStatus } from '../../../../detection_engine/rule_management/logic/use_pre_packaged_rules_status'; import { affectedJobIds } from '../../callouts/ml_job_compatibility_callout/affected_job_ids'; import { MlJobUpgradeModal } from '../../modals/ml_job_upgrade_modal'; @@ -27,11 +28,8 @@ interface LoadPrePackagedRulesProps { export const LoadPrePackagedRules = ({ children }: LoadPrePackagedRulesProps) => { const { isFetching: isFetchingPrepackagedStatus } = usePrePackagedRulesStatus(); - const { - createPrePackagedRules, - canCreatePrePackagedRules, - isLoading: loadingCreatePrePackagedRules, - } = useCreatePrePackagedRules(); + const isInstallingPrebuiltRules = useIsInstallingPrePackagedRules(); + const { createPrePackagedRules, canCreatePrePackagedRules } = useCreatePrePackagedRules(); const { startTransaction } = useStartTransaction(); const handleCreatePrePackagedRules = useCallback(async () => { @@ -63,7 +61,7 @@ export const LoadPrePackagedRules = ({ children }: LoadPrePackagedRulesProps) => return ( <> {children({ - isLoading: loadingCreatePrePackagedRules, + isLoading: isInstallingPrebuiltRules, isDisabled, onClick: handleInstallPrePackagedRules, })} From 745e9ad9d7d1a3958842bfe63343e2e4d00041f6 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Mon, 13 Feb 2023 16:06:11 +0100 Subject: [PATCH 129/203] [ftr] split x-pack api integration tests based on plugin (#150837) ## Summary Currently we run all x-pack api integration tests as a single piece (config) and it takes on average **33+ minutes** If a single test fails, buildkite retries the config and you have to wait another 30+ minutes to see if test passed (flaky test sign) or failed (PR broke test) image Splitting config into many small ones will not only speedup overall CI run (configs will be assigned to different workers based on its historical run time) but also speedup retry by running only a sub set of tests related to the particular config file. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .buildkite/ftr_configs.yml | 32 +++++++++++++- .../test/api_integration/apis/aiops/config.ts | 17 ++++++++ .../test/api_integration/apis/cases/config.ts | 17 ++++++++ .../apis/cloud_security_posture/config.ts | 17 ++++++++ .../api_integration/apis/console/config.ts | 17 ++++++++ x-pack/test/api_integration/apis/es/config.ts | 17 ++++++++ .../api_integration/apis/features/config.ts | 17 ++++++++ .../apis/file_upload/config.ts | 17 ++++++++ x-pack/test/api_integration/apis/index.ts | 43 ------------------- .../api_integration/apis/kibana/config.ts | 17 ++++++++ .../test/api_integration/apis/lists/config.ts | 17 ++++++++ .../api_integration/apis/logs_ui/config.ts | 17 ++++++++ .../api_integration/apis/logstash/config.ts | 17 ++++++++ .../api_integration/apis/management/config.ts | 17 ++++++++ .../test/api_integration/apis/maps/config.ts | 17 ++++++++ .../api_integration/apis/metrics_ui/config.ts | 17 ++++++++ x-pack/test/api_integration/apis/ml/config.ts | 17 ++++++++ .../api_integration/apis/monitoring/config.ts | 17 ++++++++ .../apis/monitoring_collection/config.ts | 17 ++++++++ .../api_integration/apis/osquery/config.ts | 17 ++++++++ .../apis/painless_lab/config.ts | 17 ++++++++ .../api_integration/apis/search/config.ts | 17 ++++++++ .../apis/searchprofiler/config.ts | 17 ++++++++ .../api_integration/apis/security/config.ts | 17 ++++++++ .../apis/security_solution/config.ts | 17 ++++++++ .../api_integration/apis/spaces/config.ts | 17 ++++++++ .../api_integration/apis/synthetics/config.ts | 17 ++++++++ .../api_integration/apis/telemetry/config.ts | 17 ++++++++ .../api_integration/apis/transform/config.ts | 17 ++++++++ .../apis/upgrade_assistant/config.ts | 17 ++++++++ .../api_integration/apis/uptime/config.ts | 17 ++++++++ .../monitor_states_real_data.snap | 2 +- .../api_integration/apis/watcher/config.ts | 17 ++++++++ x-pack/test/api_integration/config.ts | 1 - .../api_integration/config_security_basic.ts | 32 ++++++++------ .../api_integration/config_security_trial.ts | 16 ++++--- 36 files changed, 570 insertions(+), 66 deletions(-) create mode 100644 x-pack/test/api_integration/apis/aiops/config.ts create mode 100644 x-pack/test/api_integration/apis/cases/config.ts create mode 100644 x-pack/test/api_integration/apis/cloud_security_posture/config.ts create mode 100644 x-pack/test/api_integration/apis/console/config.ts create mode 100644 x-pack/test/api_integration/apis/es/config.ts create mode 100644 x-pack/test/api_integration/apis/features/config.ts create mode 100644 x-pack/test/api_integration/apis/file_upload/config.ts delete mode 100644 x-pack/test/api_integration/apis/index.ts create mode 100644 x-pack/test/api_integration/apis/kibana/config.ts create mode 100644 x-pack/test/api_integration/apis/lists/config.ts create mode 100644 x-pack/test/api_integration/apis/logs_ui/config.ts create mode 100644 x-pack/test/api_integration/apis/logstash/config.ts create mode 100644 x-pack/test/api_integration/apis/management/config.ts create mode 100644 x-pack/test/api_integration/apis/maps/config.ts create mode 100644 x-pack/test/api_integration/apis/metrics_ui/config.ts create mode 100644 x-pack/test/api_integration/apis/ml/config.ts create mode 100644 x-pack/test/api_integration/apis/monitoring/config.ts create mode 100644 x-pack/test/api_integration/apis/monitoring_collection/config.ts create mode 100644 x-pack/test/api_integration/apis/osquery/config.ts create mode 100644 x-pack/test/api_integration/apis/painless_lab/config.ts create mode 100644 x-pack/test/api_integration/apis/search/config.ts create mode 100644 x-pack/test/api_integration/apis/searchprofiler/config.ts create mode 100644 x-pack/test/api_integration/apis/security/config.ts create mode 100644 x-pack/test/api_integration/apis/security_solution/config.ts create mode 100644 x-pack/test/api_integration/apis/spaces/config.ts create mode 100644 x-pack/test/api_integration/apis/synthetics/config.ts create mode 100644 x-pack/test/api_integration/apis/telemetry/config.ts create mode 100644 x-pack/test/api_integration/apis/transform/config.ts create mode 100644 x-pack/test/api_integration/apis/upgrade_assistant/config.ts create mode 100644 x-pack/test/api_integration/apis/uptime/config.ts create mode 100644 x-pack/test/api_integration/apis/watcher/config.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 27516d92de621..2bfcce064d5ce 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -11,6 +11,7 @@ disabled: - x-pack/test/localization/config.base.ts - test/server_integration/config.base.js - x-pack/test/functional_with_es_ssl/config.base.ts + - x-pack/test/api_integration/config.ts # QA suites that are run out-of-band - x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js @@ -143,7 +144,36 @@ enabled: - x-pack/test/api_integration_basic/config.ts - x-pack/test/api_integration/config_security_basic.ts - x-pack/test/api_integration/config_security_trial.ts - - x-pack/test/api_integration/config.ts + - x-pack/test/api_integration/apis/aiops/config.ts + - x-pack/test/api_integration/apis/cases/config.ts + - x-pack/test/api_integration/apis/cloud_security_posture/config.ts + - x-pack/test/api_integration/apis/console/config.ts + - x-pack/test/api_integration/apis/es/config.ts + - x-pack/test/api_integration/apis/features/config.ts + - x-pack/test/api_integration/apis/file_upload/config.ts + - x-pack/test/api_integration/apis/kibana/config.ts + - x-pack/test/api_integration/apis/lists/config.ts + - x-pack/test/api_integration/apis/logs_ui/config.ts + - x-pack/test/api_integration/apis/logstash/config.ts + - x-pack/test/api_integration/apis/management/config.ts + - x-pack/test/api_integration/apis/maps/config.ts + - x-pack/test/api_integration/apis/metrics_ui/config.ts + - x-pack/test/api_integration/apis/ml/config.ts + - x-pack/test/api_integration/apis/monitoring/config.ts + - x-pack/test/api_integration/apis/monitoring_collection/config.ts + - x-pack/test/api_integration/apis/osquery/config.ts + - x-pack/test/api_integration/apis/painless_lab/config.ts + - x-pack/test/api_integration/apis/search/config.ts + - x-pack/test/api_integration/apis/searchprofiler/config.ts + - x-pack/test/api_integration/apis/security/config.ts + - x-pack/test/api_integration/apis/security_solution/config.ts + - x-pack/test/api_integration/apis/spaces/config.ts + - x-pack/test/api_integration/apis/synthetics/config.ts + - x-pack/test/api_integration/apis/telemetry/config.ts + - x-pack/test/api_integration/apis/transform/config.ts + - x-pack/test/api_integration/apis/upgrade_assistant/config.ts + - x-pack/test/api_integration/apis/uptime/config.ts + - x-pack/test/api_integration/apis/watcher/config.ts - x-pack/test/apm_api_integration/basic/config.ts - x-pack/test/apm_api_integration/rules/config.ts - x-pack/test/apm_api_integration/trial/config.ts diff --git a/x-pack/test/api_integration/apis/aiops/config.ts b/x-pack/test/api_integration/apis/aiops/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/aiops/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/cases/config.ts b/x-pack/test/api_integration/apis/cases/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/cases/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/config.ts b/x-pack/test/api_integration/apis/cloud_security_posture/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/cloud_security_posture/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/console/config.ts b/x-pack/test/api_integration/apis/console/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/console/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/es/config.ts b/x-pack/test/api_integration/apis/es/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/es/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/features/config.ts b/x-pack/test/api_integration/apis/features/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/features/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/file_upload/config.ts b/x-pack/test/api_integration/apis/file_upload/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/file_upload/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/index.ts b/x-pack/test/api_integration/apis/index.ts deleted file mode 100644 index 0278c439c5995..0000000000000 --- a/x-pack/test/api_integration/apis/index.ts +++ /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 { FtrProviderContext } from '../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('apis', function () { - loadTestFile(require.resolve('./search')); - loadTestFile(require.resolve('./es')); - loadTestFile(require.resolve('./security')); - loadTestFile(require.resolve('./spaces')); - loadTestFile(require.resolve('./monitoring')); - loadTestFile(require.resolve('./features')); - loadTestFile(require.resolve('./telemetry')); - loadTestFile(require.resolve('./logstash')); - loadTestFile(require.resolve('./kibana')); - loadTestFile(require.resolve('./metrics_ui')); - loadTestFile(require.resolve('./console')); - loadTestFile(require.resolve('./management')); - loadTestFile(require.resolve('./uptime')); - loadTestFile(require.resolve('./synthetics')); - loadTestFile(require.resolve('./maps')); - loadTestFile(require.resolve('./security_solution')); - loadTestFile(require.resolve('./transform')); - loadTestFile(require.resolve('./lists')); - loadTestFile(require.resolve('./upgrade_assistant')); - loadTestFile(require.resolve('./searchprofiler')); - loadTestFile(require.resolve('./painless_lab')); - loadTestFile(require.resolve('./file_upload')); - loadTestFile(require.resolve('./aiops')); - loadTestFile(require.resolve('./ml')); - loadTestFile(require.resolve('./watcher')); - loadTestFile(require.resolve('./logs_ui')); - loadTestFile(require.resolve('./osquery')); - loadTestFile(require.resolve('./cases')); - loadTestFile(require.resolve('./monitoring_collection')); - loadTestFile(require.resolve('./cloud_security_posture')); - }); -} diff --git a/x-pack/test/api_integration/apis/kibana/config.ts b/x-pack/test/api_integration/apis/kibana/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/kibana/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/lists/config.ts b/x-pack/test/api_integration/apis/lists/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/lists/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/logs_ui/config.ts b/x-pack/test/api_integration/apis/logs_ui/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/logs_ui/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/logstash/config.ts b/x-pack/test/api_integration/apis/logstash/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/logstash/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/management/config.ts b/x-pack/test/api_integration/apis/management/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/management/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/maps/config.ts b/x-pack/test/api_integration/apis/maps/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/maps/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/metrics_ui/config.ts b/x-pack/test/api_integration/apis/metrics_ui/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/metrics_ui/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/ml/config.ts b/x-pack/test/api_integration/apis/ml/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/monitoring/config.ts b/x-pack/test/api_integration/apis/monitoring/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/monitoring_collection/config.ts b/x-pack/test/api_integration/apis/monitoring_collection/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/monitoring_collection/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/osquery/config.ts b/x-pack/test/api_integration/apis/osquery/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/osquery/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/painless_lab/config.ts b/x-pack/test/api_integration/apis/painless_lab/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/painless_lab/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/search/config.ts b/x-pack/test/api_integration/apis/search/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/search/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/searchprofiler/config.ts b/x-pack/test/api_integration/apis/searchprofiler/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/searchprofiler/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/security/config.ts b/x-pack/test/api_integration/apis/security/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/security/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/security_solution/config.ts b/x-pack/test/api_integration/apis/security_solution/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/security_solution/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/spaces/config.ts b/x-pack/test/api_integration/apis/spaces/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/spaces/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/synthetics/config.ts b/x-pack/test/api_integration/apis/synthetics/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/synthetics/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/telemetry/config.ts b/x-pack/test/api_integration/apis/telemetry/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/telemetry/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/transform/config.ts b/x-pack/test/api_integration/apis/transform/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/transform/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/config.ts b/x-pack/test/api_integration/apis/upgrade_assistant/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/upgrade_assistant/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/uptime/config.ts b/x-pack/test/api_integration/apis/uptime/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/uptime/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/apis/uptime/rest/__snapshots__/monitor_states_real_data.snap b/x-pack/test/api_integration/apis/uptime/rest/__snapshots__/monitor_states_real_data.snap index 81348cfa2bb28..5bdccdcbb0c49 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/__snapshots__/monitor_states_real_data.snap +++ b/x-pack/test/api_integration/apis/uptime/rest/__snapshots__/monitor_states_real_data.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`apis uptime uptime REST endpoints with real-world data monitor states endpoint will fetch monitor state data for the given down filters 1`] = ` +exports[`uptime uptime REST endpoints with real-world data monitor states endpoint will fetch monitor state data for the given down filters 1`] = ` Object { "nextPagePagination": "{\\"cursorDirection\\":\\"AFTER\\",\\"sortOrder\\":\\"ASC\\",\\"cursorKey\\":{\\"monitor_id\\":\\"0020-down\\"}}", "prevPagePagination": null, diff --git a/x-pack/test/api_integration/apis/watcher/config.ts b/x-pack/test/api_integration/apis/watcher/config.ts new file mode 100644 index 0000000000000..5f335f116fefe --- /dev/null +++ b/x-pack/test/api_integration/apis/watcher/config.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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../config.ts')); + + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index cf87502f5c0c7..5766a9efdf982 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -14,7 +14,6 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi ); return { - testFiles: [require.resolve('./apis')], services, servers: xPackFunctionalTestsConfig.get('servers'), security: xPackFunctionalTestsConfig.get('security'), diff --git a/x-pack/test/api_integration/config_security_basic.ts b/x-pack/test/api_integration/config_security_basic.ts index fc32e66c63e9e..0164e8f54f822 100644 --- a/x-pack/test/api_integration/config_security_basic.ts +++ b/x-pack/test/api_integration/config_security_basic.ts @@ -8,19 +8,25 @@ /* eslint-disable import/no-default-export */ import { FtrConfigProviderContext } from '@kbn/test'; -import { default as createTestConfig } from './config'; -export default async function (context: FtrConfigProviderContext) { +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('./config.ts')); // security APIs should function the same under a basic or trial license - return createTestConfig(context).then((config) => { - config.esTestCluster.license = 'basic'; - config.esTestCluster.serverArgs = [ - 'xpack.license.self_generated.type=basic', - 'xpack.security.enabled=true', - 'xpack.security.authc.api_key.enabled=true', - ]; - config.testFiles = [require.resolve('./apis/security/security_basic')]; - config.junit.reportName = 'X-Pack API Integration Tests (Security Basic)'; - return config; - }); + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('./apis/security/security_basic')], + esTestCluster: { + ...baseIntegrationTestsConfig.get('esTestCluster'), + license: 'basic', + serverArgs: [ + ...baseIntegrationTestsConfig.get('esTestCluster.serverArgs'), + 'xpack.license.self_generated.type=basic', + 'xpack.security.enabled=true', + 'xpack.security.authc.api_key.enabled=true', + ], + }, + junit: { + reportName: 'X-Pack API Integration Tests (Security Basic)', + }, + }; } diff --git a/x-pack/test/api_integration/config_security_trial.ts b/x-pack/test/api_integration/config_security_trial.ts index 93b1eefd350e9..4559dcd7b0ebb 100644 --- a/x-pack/test/api_integration/config_security_trial.ts +++ b/x-pack/test/api_integration/config_security_trial.ts @@ -8,12 +8,14 @@ /* eslint-disable import/no-default-export */ import { FtrConfigProviderContext } from '@kbn/test'; -import { default as createTestConfig } from './config'; -export default async function (context: FtrConfigProviderContext) { - return createTestConfig(context).then((config) => { - config.testFiles = [require.resolve('./apis/security/security_trial')]; - config.junit.reportName = 'X-Pack API Integration Tests (Security Trial)'; - return config; - }); +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const baseIntegrationTestsConfig = await readConfigFile(require.resolve('./config.ts')); + return { + ...baseIntegrationTestsConfig.getAll(), + testFiles: [require.resolve('./apis/security/security_trial')], + junit: { + reportName: 'X-Pack API Integration Tests (Security Trial)', + }, + }; } From 76dd2dcc2dbd0ee4bc7e140a293adce45688431d Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 13 Feb 2023 15:15:21 +0000 Subject: [PATCH 130/203] skip flaky suite (#150962) --- .../security_and_spaces/tests/trial/cases/push_case.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts index a18c24c62652d..d6d0919be8b4a 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts @@ -616,7 +616,8 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - describe('alerts', () => { + // FLAKY: https://github.com/elastic/kibana/issues/150962 + describe.skip('alerts', () => { const defaultSignalsIndex = '.siem-signals-default-000001'; const signalID = '4679431ee0ba3209b6fcd60a255a696886fe0a7d18f5375de510ff5b68fa6b78'; const signalID2 = '1023bcfea939643c5e51fd8df53797e0ea693cee547db579ab56d96402365c1e'; From 075793031faf1a2de9aa57cf04a43dfa80b8448b Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Mon, 13 Feb 2023 10:36:35 -0500 Subject: [PATCH 131/203] [Security Solution][Endpoint] Update 'run endpoint' CLI tool so that the created Endpoint Policy has all protections enabled (#150789) ## Summary - Updated the Endpoint Run CLI tool to enable all policy protections whenever it creates a policy for testing. --- .../endpoint_agent_runner/elastic_endpoint.ts | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/scripts/endpoint/endpoint_agent_runner/elastic_endpoint.ts b/x-pack/plugins/security_solution/scripts/endpoint/endpoint_agent_runner/elastic_endpoint.ts index 7df5030a70091..e0938707ea5a0 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/endpoint_agent_runner/elastic_endpoint.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/endpoint_agent_runner/elastic_endpoint.ts @@ -8,8 +8,14 @@ import { userInfo } from 'os'; import execa from 'execa'; import nodeFetch from 'node-fetch'; -import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; +import { + AGENT_POLICY_SAVED_OBJECT_TYPE, + packagePolicyRouteService, + type UpdatePackagePolicyResponse, + type UpdatePackagePolicy, +} from '@kbn/fleet-plugin/common'; import chalk from 'chalk'; +import { inspect } from 'util'; import { getEndpointPackageInfo } from '../../../common/endpoint/index_data'; import { indexFleetEndpointPolicy } from '../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; import { @@ -19,6 +25,7 @@ import { waitForHostToEnroll, } from '../common/fleet_services'; import { getRuntimeServices } from './runtime'; +import { type PolicyData, ProtectionModes } from '../../../common/endpoint/types'; interface ElasticArtifactSearchResponse { manifest: { @@ -153,7 +160,7 @@ export const enrollEndpointHost = async () => { Delete VM: ${chalk.bold(`multipass delete -p ${vmName}${await getVmCountNotice()}`)} `); } catch (error) { - log.error(error); + log.error(inspect(error, { depth: 4 })); log.indent(-4); throw error; } @@ -215,9 +222,40 @@ const getOrCreateAgentPolicyId = async (): Promise => { endpointPackageVersion, agentPolicyName ); - const agentPolicy = response.agentPolicies[0]; + // Update the Endpoint integration policy to enable all protections + // eslint-disable-next-line @typescript-eslint/naming-convention + const { created_by, created_at, updated_at, updated_by, id, version, revision, ...restOfPolicy } = + response.integrationPolicies[0]; + const updatedEndpointPolicy: UpdatePackagePolicy = restOfPolicy; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const policy = updatedEndpointPolicy!.inputs[0]!.config!.policy.value; + + policy.mac.malware.mode = ProtectionModes.prevent; + policy.windows.malware.mode = ProtectionModes.prevent; + policy.linux.malware.mode = ProtectionModes.prevent; + + policy.mac.memory_protection.mode = ProtectionModes.prevent; + policy.windows.memory_protection.mode = ProtectionModes.prevent; + policy.linux.memory_protection.mode = ProtectionModes.prevent; + + policy.mac.behavior_protection.mode = ProtectionModes.prevent; + policy.windows.behavior_protection.mode = ProtectionModes.prevent; + policy.linux.behavior_protection.mode = ProtectionModes.prevent; + + policy.windows.ransomware.mode = ProtectionModes.prevent; + + response.integrationPolicies[0] = ( + await kbnClient + .request({ + method: 'PUT', + path: packagePolicyRouteService.getUpdatePath(response.integrationPolicies[0].id), + body: updatedEndpointPolicy, + }) + .then((res) => res.data) + ).item as PolicyData; + log.info(`New agent policy with Endpoint integration created: Name: ${agentPolicy.name} Id: ${agentPolicy.id}`); From 8f4e5c53ff57e7b32d7d52d9ed9528ea216aafd1 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Mon, 13 Feb 2023 09:32:08 -0700 Subject: [PATCH 132/203] [Saved Objects] Logs warning when deprecated SO APIs are called (#150775) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/routes/bulk_create.ts | 7 ++++- .../src/routes/bulk_delete.ts | 7 ++++- .../src/routes/bulk_get.ts | 5 +++- .../src/routes/bulk_resolve.ts | 7 ++++- .../src/routes/bulk_update.ts | 7 ++++- .../src/routes/create.ts | 5 +++- .../src/routes/delete.ts | 5 +++- .../src/routes/find.ts | 5 +++- .../src/routes/get.ts | 5 +++- .../src/routes/index.ts | 22 +++++++------- .../src/routes/resolve.ts | 7 ++++- .../src/routes/update.ts | 5 +++- .../saved_objects/routes/bulk_create.test.ts | 23 ++++++++++++++- .../saved_objects/routes/bulk_delete.test.ts | 19 +++++++++++- .../saved_objects/routes/bulk_get.test.ts | 19 +++++++++++- .../saved_objects/routes/bulk_resolve.test.ts | 19 +++++++++++- .../saved_objects/routes/bulk_update.test.ts | 29 ++++++++++++++++++- .../saved_objects/routes/create.test.ts | 18 +++++++++++- .../saved_objects/routes/delete.test.ts | 13 ++++++++- .../saved_objects/routes/find.test.ts | 13 ++++++++- .../saved_objects/routes/get.test.ts | 13 ++++++++- .../saved_objects/routes/resolve.test.ts | 13 ++++++++- .../saved_objects/routes/update.test.ts | 14 ++++++++- 23 files changed, 247 insertions(+), 33 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_create.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_create.ts index fd32068d79ebf..9c85b1aa0620c 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_create.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_create.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfAnyTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerBulkCreateRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.post( { @@ -49,6 +51,9 @@ export const registerBulkCreateRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn( + "The bulk create saved object API '/api/saved_objects/_bulk_create' is deprecated." + ); const { overwrite } = req.query; const usageStatsClient = coreUsageData.getClient(); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts index 720bd6ecdb7e1..cbd22f827a642 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfAnyTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerBulkDeleteRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.post( { @@ -35,6 +37,9 @@ export const registerBulkDeleteRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn( + "The bulk update saved object API '/api/saved_objects/_bulk_update' is deprecated." + ); const { force } = req.query; const usageStatsClient = coreUsageData.getClient(); usageStatsClient.incrementSavedObjectsBulkDelete({ request: req }).catch(() => {}); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_get.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_get.ts index 30a9a1625c39d..455657d9ca640 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_get.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_get.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfAnyTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerBulkGetRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.post( { @@ -34,6 +36,7 @@ export const registerBulkGetRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn("The bulk get saved object API '/api/saved_objects/_bulk_get' is deprecated."); const usageStatsClient = coreUsageData.getClient(); usageStatsClient.incrementSavedObjectsBulkGet({ request: req }).catch(() => {}); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_resolve.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_resolve.ts index 77f3d480bcdef..874df9f59bb8c 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_resolve.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_resolve.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfAnyTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerBulkResolveRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.post( { @@ -32,6 +34,9 @@ export const registerBulkResolveRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn( + "The bulk resolve saved object API '/api/saved_objects/_bulk_resolve' is deprecated." + ); const usageStatsClient = coreUsageData.getClient(); usageStatsClient.incrementSavedObjectsBulkResolve({ request: req }).catch(() => {}); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_update.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_update.ts index b198ef2ad5fec..b51e39fd1c6d5 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_update.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_update.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfAnyTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerBulkUpdateRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.put( { @@ -44,6 +46,9 @@ export const registerBulkUpdateRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn( + "The bulk update saved object API '/api/saved_objects/_bulk_update' is deprecated." + ); const usageStatsClient = coreUsageData.getClient(); usageStatsClient.incrementSavedObjectsBulkUpdate({ request: req }).catch(() => {}); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/create.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/create.ts index fcdb1fef13889..af0be90481c33 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/create.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/create.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerCreateRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.post( { @@ -48,6 +50,7 @@ export const registerCreateRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn("The create saved object API '/api/saved_objects/{type}/{id}' is deprecated."); const { type, id } = req.params; const { overwrite } = req.query; const { attributes, migrationVersion, coreMigrationVersion, references, initialNamespaces } = diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/delete.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/delete.ts index eea862e64008b..71124fee2ca38 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/delete.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/delete.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerDeleteRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.delete( { @@ -33,6 +35,7 @@ export const registerDeleteRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn("The delete saved object API '/api/saved_objects/{type}/{id}' is deprecated."); const { type, id } = req.params; const { force } = req.query; const { getClient, typeRegistry } = (await context.core).savedObjects; diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/find.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/find.ts index a2d4497dd5f6e..42cf0290b52d2 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/find.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/find.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwOnHttpHiddenTypes } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerFindRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { const referenceSchema = schema.object({ type: schema.string(), @@ -59,6 +61,7 @@ export const registerFindRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn("The find saved object API '/api/saved_objects/_find' is deprecated."); const query = req.query; const namespaces = diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/get.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/get.ts index b8c1ab5614b7a..ecacdc4452c67 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/get.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/get.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerGetRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.get( { @@ -30,6 +32,7 @@ export const registerGetRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn("The get saved object API '/api/saved_objects/{type}/{id}' is deprecated."); const { type, id } = req.params; const usageStatsClient = coreUsageData.getClient(); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts index 89d5b41dd8885..8c85017064498 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/index.ts @@ -53,17 +53,17 @@ export function registerRoutes({ const router = http.createRouter('/api/saved_objects/'); - registerGetRoute(router, { coreUsageData }); - registerResolveRoute(router, { coreUsageData }); - registerCreateRoute(router, { coreUsageData }); - registerDeleteRoute(router, { coreUsageData }); - registerFindRoute(router, { coreUsageData }); - registerUpdateRoute(router, { coreUsageData }); - registerBulkGetRoute(router, { coreUsageData }); - registerBulkCreateRoute(router, { coreUsageData }); - registerBulkResolveRoute(router, { coreUsageData }); - registerBulkUpdateRoute(router, { coreUsageData }); - registerBulkDeleteRoute(router, { coreUsageData }); + registerGetRoute(router, { coreUsageData, logger }); + registerResolveRoute(router, { coreUsageData, logger }); + registerCreateRoute(router, { coreUsageData, logger }); + registerDeleteRoute(router, { coreUsageData, logger }); + registerFindRoute(router, { coreUsageData, logger }); + registerUpdateRoute(router, { coreUsageData, logger }); + registerBulkGetRoute(router, { coreUsageData, logger }); + registerBulkCreateRoute(router, { coreUsageData, logger }); + registerBulkResolveRoute(router, { coreUsageData, logger }); + registerBulkUpdateRoute(router, { coreUsageData, logger }); + registerBulkDeleteRoute(router, { coreUsageData, logger }); registerExportRoute(router, { config, coreUsageData }); registerImportRoute(router, { config, coreUsageData }); registerResolveImportErrorsRoute(router, { config, coreUsageData }); diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/resolve.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/resolve.ts index ac8d4fdcc5ba7..be77423cba09b 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/resolve.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/resolve.ts @@ -8,16 +8,18 @@ import { schema } from '@kbn/config-schema'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; +import type { Logger } from '@kbn/logging'; import type { InternalSavedObjectRouter } from '../internal_types'; import { throwIfTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerResolveRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.get( { @@ -30,6 +32,9 @@ export const registerResolveRoute = ( }, }, router.handleLegacyErrors(async (context, req, res) => { + logger.warn( + "The resolve saved object API '/api/saved_objects/resolve/{type}/{id}' is deprecated." + ); const { type, id } = req.params; const { savedObjects } = await context.core; diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts index 491add9a182ca..d1b544519efa3 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts @@ -8,17 +8,19 @@ import { schema } from '@kbn/config-schema'; import type { SavedObjectsUpdateOptions } from '@kbn/core-saved-objects-api-server'; +import type { Logger } from '@kbn/logging'; import type { InternalCoreUsageDataSetup } from '@kbn/core-usage-data-base-server-internal'; import type { InternalSavedObjectRouter } from '../internal_types'; import { catchAndReturnBoomErrors, throwIfTypeNotVisibleByAPI } from './utils'; interface RouteDependencies { coreUsageData: InternalCoreUsageDataSetup; + logger: Logger; } export const registerUpdateRoute = ( router: InternalSavedObjectRouter, - { coreUsageData }: RouteDependencies + { coreUsageData, logger }: RouteDependencies ) => { router.put( { @@ -45,6 +47,7 @@ export const registerUpdateRoute = ( }, }, catchAndReturnBoomErrors(async (context, req, res) => { + logger.warn("The update saved object API '/api/saved_objects/{type}/{id}' is deprecated."); const { type, id } = req.params; const { attributes, version, references, upsert } = req.body; const options: SavedObjectsUpdateOptions = { version, references, upsert }; diff --git a/src/core/server/integration_tests/saved_objects/routes/bulk_create.test.ts b/src/core/server/integration_tests/saved_objects/routes/bulk_create.test.ts index aba1f322f3bd2..096d7f330abca 100644 --- a/src/core/server/integration_tests/saved_objects/routes/bulk_create.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/bulk_create.test.ts @@ -19,6 +19,7 @@ import { type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; import { createHiddenTypeVariants, setupServer } from '@kbn/core-test-helpers-test-utils'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -33,6 +34,7 @@ describe('POST /api/saved_objects/_bulk_create', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); @@ -50,7 +52,9 @@ describe('POST /api/saved_objects/_bulk_create', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkCreate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerBulkCreateRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerBulkCreateRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -161,4 +165,21 @@ describe('POST /api/saved_objects/_bulk_create', () => { 'Unsupported saved object type(s): hidden-from-http: Bad Request' ); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .post('/api/saved_objects/_bulk_create') + .send([ + { + id: 'abc1234', + type: 'index-pattern', + attributes: { + title: 'foo', + }, + references: [], + }, + ]) + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/bulk_delete.test.ts b/src/core/server/integration_tests/saved_objects/routes/bulk_delete.test.ts index f05780cc0fd65..47559aecf9769 100644 --- a/src/core/server/integration_tests/saved_objects/routes/bulk_delete.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/bulk_delete.test.ts @@ -18,6 +18,7 @@ import { registerBulkDeleteRoute, type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -32,6 +33,7 @@ describe('POST /api/saved_objects/_bulk_delete', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); @@ -52,7 +54,9 @@ describe('POST /api/saved_objects/_bulk_delete', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkDelete.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerBulkDeleteRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerBulkDeleteRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -133,4 +137,17 @@ describe('POST /api/saved_objects/_bulk_delete', () => { .expect(400); expect(result.body.message).toContain('Unsupported saved object type(s):'); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .post('/api/saved_objects/_bulk_delete') + .send([ + { + id: 'hiddenID', + type: 'hidden-from-http', + }, + ]) + .expect(400); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/bulk_get.test.ts b/src/core/server/integration_tests/saved_objects/routes/bulk_get.test.ts index fdd23217891c4..7c894c250dceb 100644 --- a/src/core/server/integration_tests/saved_objects/routes/bulk_get.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/bulk_get.test.ts @@ -18,6 +18,7 @@ import { registerBulkGetRoute, type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -32,6 +33,7 @@ describe('POST /api/saved_objects/_bulk_get', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); @@ -51,7 +53,9 @@ describe('POST /api/saved_objects/_bulk_get', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkGet.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerBulkGetRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerBulkGetRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -120,4 +124,17 @@ describe('POST /api/saved_objects/_bulk_get', () => { .expect(400); expect(result.body.message).toContain('Unsupported saved object type(s):'); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .post('/api/saved_objects/_bulk_get') + .send([ + { + id: 'abc123', + type: 'index-pattern', + }, + ]) + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/bulk_resolve.test.ts b/src/core/server/integration_tests/saved_objects/routes/bulk_resolve.test.ts index 3ea1e0c9580ac..98253fabb2fa4 100644 --- a/src/core/server/integration_tests/saved_objects/routes/bulk_resolve.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/bulk_resolve.test.ts @@ -18,6 +18,7 @@ import { registerBulkResolveRoute, type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -32,6 +33,7 @@ describe('POST /api/saved_objects/_bulk_resolve', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); @@ -52,7 +54,9 @@ describe('POST /api/saved_objects/_bulk_resolve', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkResolve.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerBulkResolveRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerBulkResolveRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -124,4 +128,17 @@ describe('POST /api/saved_objects/_bulk_resolve', () => { .expect(400); expect(result.body.message).toContain('Unsupported saved object type(s):'); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .post('/api/saved_objects/_bulk_resolve') + .send([ + { + id: 'abc123', + type: 'index-pattern', + }, + ]) + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/bulk_update.test.ts b/src/core/server/integration_tests/saved_objects/routes/bulk_update.test.ts index 04ad9dcd40592..eb50fd141e2af 100644 --- a/src/core/server/integration_tests/saved_objects/routes/bulk_update.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/bulk_update.test.ts @@ -18,6 +18,7 @@ import { registerBulkUpdateRoute, type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -34,6 +35,7 @@ describe('PUT /api/saved_objects/_bulk_update', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); @@ -51,7 +53,9 @@ describe('PUT /api/saved_objects/_bulk_update', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsBulkUpdate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerBulkUpdateRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerBulkUpdateRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -169,4 +173,27 @@ describe('PUT /api/saved_objects/_bulk_update', () => { .expect(400); expect(result.body.message).toContain('Unsupported saved object type(s):'); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .put('/api/saved_objects/_bulk_update') + .send([ + { + type: 'visualization', + id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', + attributes: { + title: 'An existing visualization', + }, + }, + { + type: 'dashboard', + id: 'be3733a0-9efe-11e7-acb3-3dab96693fab', + attributes: { + title: 'An existing dashboard', + }, + }, + ]) + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/create.test.ts b/src/core/server/integration_tests/saved_objects/routes/create.test.ts index 50791be209547..bf67325a8e756 100644 --- a/src/core/server/integration_tests/saved_objects/routes/create.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/create.test.ts @@ -18,6 +18,7 @@ import { registerCreateRoute, type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -32,6 +33,7 @@ describe('POST /api/saved_objects/{type}', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; const clientResponse = { id: 'logstash-*', @@ -52,7 +54,9 @@ describe('POST /api/saved_objects/{type}', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsCreate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerCreateRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerCreateRoute(router, { coreUsageData, logger }); handlerContext.savedObjects.typeRegistry.getType.mockImplementation((typename: string) => { return testTypes @@ -145,4 +149,16 @@ describe('POST /api/saved_objects/{type}', () => { expect(result.body.message).toContain("Unsupported saved object type: 'hidden-from-http'"); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .post('/api/saved_objects/index-pattern') + .send({ + attributes: { + title: 'Logging test', + }, + }) + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/delete.test.ts b/src/core/server/integration_tests/saved_objects/routes/delete.test.ts index 42c97c0c565da..538cc2d721485 100644 --- a/src/core/server/integration_tests/saved_objects/routes/delete.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/delete.test.ts @@ -18,6 +18,7 @@ import { registerDeleteRoute, type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -33,6 +34,7 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { ({ server, httpSetup, handlerContext } = await setupServer()); @@ -49,7 +51,9 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsDelete.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerDeleteRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerDeleteRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -104,4 +108,11 @@ describe('DELETE /api/saved_objects/{type}/{id}', () => { .expect(400); expect(result.body.message).toContain("Unsupported saved object type: 'hidden-from-http'"); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .delete('/api/saved_objects/index-pattern/logstash-*') + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/find.test.ts b/src/core/server/integration_tests/saved_objects/routes/find.test.ts index 2185edd9f5e19..25fd8a32fc9ef 100644 --- a/src/core/server/integration_tests/saved_objects/routes/find.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/find.test.ts @@ -16,6 +16,7 @@ import { coreUsageDataServiceMock, } from '@kbn/core-usage-data-server-mocks'; import { createHiddenTypeVariants, setupServer } from '@kbn/core-test-helpers-test-utils'; +import { loggerMock } from '@kbn/logging-mocks'; import { registerFindRoute, type InternalSavedObjectsRequestHandlerContext, @@ -38,6 +39,7 @@ describe('GET /api/saved_objects/_find', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; const clientResponse = { total: 0, @@ -64,7 +66,9 @@ describe('GET /api/saved_objects/_find', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsFind.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerFindRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerFindRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -428,4 +432,11 @@ describe('GET /api/saved_objects/_find', () => { }) ); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .get('/api/saved_objects/_find?type=foo&type=bar') + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/get.test.ts b/src/core/server/integration_tests/saved_objects/routes/get.test.ts index efd7f25938592..363f0406b2148 100644 --- a/src/core/server/integration_tests/saved_objects/routes/get.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/get.test.ts @@ -23,6 +23,7 @@ import { type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; import { createHiddenTypeVariants } from '@kbn/core-test-helpers-test-utils'; +import { loggerMock } from '@kbn/logging-mocks'; const coreId = Symbol('core'); @@ -38,6 +39,7 @@ describe('GET /api/saved_objects/{type}/{id}', () => { let handlerContext: ReturnType; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { const coreContext = createCoreContext({ coreId }); @@ -72,7 +74,9 @@ describe('GET /api/saved_objects/{type}/{id}', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsGet.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerGetRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerGetRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -121,4 +125,11 @@ describe('GET /api/saved_objects/{type}/{id}', () => { .expect(400); expect(result.body.message).toContain("Unsupported saved object type: 'hidden-from-http'"); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .get('/api/saved_objects/index-pattern/logstash-*') + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/resolve.test.ts b/src/core/server/integration_tests/saved_objects/routes/resolve.test.ts index 6f58e31334764..0ecc6221730ff 100644 --- a/src/core/server/integration_tests/saved_objects/routes/resolve.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/resolve.test.ts @@ -23,6 +23,7 @@ import { type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; import { createHiddenTypeVariants } from '@kbn/core-test-helpers-test-utils'; +import { loggerMock } from '@kbn/logging-mocks'; const coreId = Symbol('core'); @@ -38,6 +39,7 @@ describe('GET /api/saved_objects/resolve/{type}/{id}', () => { let handlerContext: ReturnType; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { const coreContext = createCoreContext({ coreId }); @@ -73,7 +75,9 @@ describe('GET /api/saved_objects/resolve/{type}/{id}', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsResolve.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerResolveRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerResolveRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -122,4 +126,11 @@ describe('GET /api/saved_objects/resolve/{type}/{id}', () => { .expect(400); expect(result.body.message).toContain("Unsupported saved object type: 'hidden-from-http'"); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .get('/api/saved_objects/resolve/index-pattern/logstash-*') + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); diff --git a/src/core/server/integration_tests/saved_objects/routes/update.test.ts b/src/core/server/integration_tests/saved_objects/routes/update.test.ts index 639f503d050d7..8333159b8e1c6 100644 --- a/src/core/server/integration_tests/saved_objects/routes/update.test.ts +++ b/src/core/server/integration_tests/saved_objects/routes/update.test.ts @@ -18,6 +18,7 @@ import { registerUpdateRoute, type InternalSavedObjectsRequestHandlerContext, } from '@kbn/core-saved-objects-server-internal'; +import { loggerMock } from '@kbn/logging-mocks'; type SetupServerReturn = Awaited>; @@ -33,6 +34,7 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { let handlerContext: SetupServerReturn['handlerContext']; let savedObjectsClient: ReturnType; let coreUsageStatsClient: jest.Mocked; + let loggerWarnSpy: jest.SpyInstance; beforeEach(async () => { const clientResponse = { @@ -60,7 +62,9 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { coreUsageStatsClient = coreUsageStatsClientMock.create(); coreUsageStatsClient.incrementSavedObjectsUpdate.mockRejectedValue(new Error('Oh no!')); // intentionally throw this error, which is swallowed, so we can assert that the operation does not fail const coreUsageData = coreUsageDataServiceMock.createSetupContract(coreUsageStatsClient); - registerUpdateRoute(router, { coreUsageData }); + const logger = loggerMock.create(); + loggerWarnSpy = jest.spyOn(logger, 'warn').mockImplementation(); + registerUpdateRoute(router, { coreUsageData, logger }); await server.start(); }); @@ -123,4 +127,12 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { .expect(400); expect(result.body.message).toContain("Unsupported saved object type: 'hidden-from-http'"); }); + + it('logs a warning message when called', async () => { + await supertest(httpSetup.server.listener) + .put('/api/saved_objects/index-pattern/logstash-*') + .send({ attributes: { title: 'Logging test' }, version: 'log' }) + .expect(200); + expect(loggerWarnSpy).toHaveBeenCalledTimes(1); + }); }); From b37d3fbf01c357bcd226a5fd1369d4f1f461cc9d Mon Sep 17 00:00:00 2001 From: Angelo Gulina Date: Mon, 13 Feb 2023 17:38:28 +0100 Subject: [PATCH 133/203] Fix function expression in example (#150978) ## Summary The MR fixes the function expression syntax in an example in docs. The changes have no visual/UI impact. ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- src/core/CORE_CONVENTIONS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/CORE_CONVENTIONS.md b/src/core/CORE_CONVENTIONS.md index 1cd997d570b6a..9571be679ce57 100644 --- a/src/core/CORE_CONVENTIONS.md +++ b/src/core/CORE_CONVENTIONS.md @@ -122,7 +122,7 @@ area of Core API's and does not apply to internal types. ```ts // -- good -- - const createMock => { + const createMock = () => { const mocked: jest.Mocked = { start: jest.fn(), }; From b0c1d5c1b574fa6a6a52eb4460646e25225dc673 Mon Sep 17 00:00:00 2001 From: Or Ouziel Date: Mon, 13 Feb 2023 18:58:48 +0200 Subject: [PATCH 134/203] [Cloud Posture] Update readme with info on testing (#150430) --- .../plugins/cloud_security_posture/README.md | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/README.md b/x-pack/plugins/cloud_security_posture/README.md index a655d292c39ee..f9c760fbeb99f 100755 --- a/x-pack/plugins/cloud_security_posture/README.md +++ b/x-pack/plugins/cloud_security_posture/README.md @@ -10,7 +10,15 @@ read [Kibana Contributing Guide](https://github.com/elastic/kibana/blob/main/CON ## Testing -read [Kibana Testing Guide](https://www.elastic.co/guide/en/kibana/current/development-tests.html) for more details +for general guidelines, read [Kibana Testing Guide](https://www.elastic.co/guide/en/kibana/current/development-tests.html) for more details + +### Tests + +1. Unit Tests (Jest) - located in sibling files to the source code +2. [Integration Tests](../../test/api_integration/apis/cloud_security_posture/index.ts) +3. [End-to-End Tests](../../test/cloud_security_posture_functional/pages/index.ts) + +### Tools Run **TypeScript**: @@ -24,7 +32,7 @@ Run **ESLint**: yarn lint:es x-pack/plugins/cloud_security_posture ``` -Run **Unit Tests**: +Run [**Unit Tests**](https://www.elastic.co/guide/en/kibana/current/development-tests.html#_unit_testing): ```bash yarn test:jest --config x-pack/plugins/cloud_security_posture/jest.config.js @@ -33,24 +41,23 @@ yarn test:jest --config x-pack/plugins/cloud_security_posture/jest.config.js > **Note** > for a coverage report, add the `--coverage` flag, and run `open target/kibana-coverage/jest/x-pack/plugins/cloud_security_posture/index.html` -Run **API Integration**: +Run [**Integration Tests**](https://docs.elastic.dev/kibana-dev-docs/tutorials/testing-plugins#): ```bash yarn test:ftr --config x-pack/test/api_integration/config.ts ``` -Run **Functional UI Tests**: +Run [**End-to-End Tests**](https://www.elastic.co/guide/en/kibana/current/development-tests.html#_running_functional_tests): ```bash -yarn test:ftr --config x-pack/test/cloud_security_posture_functional/config.ts +yarn test:ftr --config x-pack/test/cloud_security_posture_functional/config.ts --debug ```
-> **Note** -> in development, run them separately with `ftr:runner` and `ftr:server` +test runner (FTR) can be used separately with `ftr:runner` and `ftr:server`: ```bash yarn test:ftr:server --config x-pack/test/api_integration/config.ts yarn test:ftr:runner --include-tag=cloud_security_posture --config x-pack/test/api_integration/config.ts -``` \ No newline at end of file +``` From 6e3551d9dad5fc15be91b37b2632064a69d491b4 Mon Sep 17 00:00:00 2001 From: Drew Tate Date: Mon, 13 Feb 2023 11:07:23 -0600 Subject: [PATCH 135/203] [Lens] Reinstate config errors in embeddable (#150650) --- .../get_application_user_messages.test.tsx | 4 +- .../get_application_user_messages.tsx | 10 +- .../editor_frame/state_helpers.ts | 2 +- .../public/embeddable/embeddable.test.tsx | 125 +++++++++--------- .../lens/public/embeddable/embeddable.tsx | 54 ++++---- .../apps/lens/group3/error_handling.ts | 22 +++ ...undamental_config_errors_on_dashboard.json | 9 ++ 7 files changed, 130 insertions(+), 96 deletions(-) create mode 100644 x-pack/test/functional/fixtures/kbn_archiver/lens/fundamental_config_errors_on_dashboard.json diff --git a/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.test.tsx b/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.test.tsx index 3691f507d6a4d..c49ef7f349f18 100644 --- a/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.test.tsx @@ -37,12 +37,12 @@ describe('application-level user messages', () => { Object { "displayLocations": Array [ Object { - "id": "visualization", + "id": "visualizationOnEmbeddable", }, ], "fixableInEditor": true, "longMessage": "Visualization type not found.", - "severity": "warning", + "severity": "error", "shortMessage": "", }, ] diff --git a/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.tsx b/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.tsx index f7b5d1eb8a135..f5190ec334157 100644 --- a/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.tsx +++ b/x-pack/plugins/lens/public/app_plugin/get_application_user_messages.tsx @@ -33,9 +33,9 @@ export const getApplicationUserMessages = ({ core, }: { visualizationType: string | null | undefined; - visualization: VisualizationState; + visualization: VisualizationState | undefined; visualizationMap: VisualizationMap; - activeDatasource: Datasource | null; + activeDatasource: Datasource | null | undefined; activeDatasourceState: { state: unknown } | null; dataViews: DataViewsState; core: CoreStart; @@ -46,7 +46,7 @@ export const getApplicationUserMessages = ({ messages.push(getMissingVisTypeError()); } - if (visualization.activeId && !visualizationMap[visualization.activeId]) { + if (visualization?.activeId && !visualizationMap[visualization.activeId]) { messages.push(getUnknownVisualizationTypeError(visualization.activeId)); } @@ -69,8 +69,8 @@ export const getApplicationUserMessages = ({ function getMissingVisTypeError(): UserMessage { return { - severity: 'warning', - displayLocations: [{ id: 'visualization' }], + severity: 'error', + displayLocations: [{ id: 'visualizationOnEmbeddable' }], fixableInEditor: true, shortMessage: '', longMessage: i18n.translate('xpack.lens.editorFrame.expressionMissingVisualizationType', { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts index 4cda8d1c7c0bd..02410b6994c34 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts @@ -401,7 +401,7 @@ export async function persistedStateToExpression( } export function getMissingIndexPattern( - currentDatasource: Datasource | null, + currentDatasource: Datasource | null | undefined, currentDatasourceState: { state: unknown } | null, indexPatterns: IndexPatternMap ) { diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx index db00db6a87f7f..92bfa95eb2aef 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.test.tsx @@ -30,23 +30,36 @@ import { OnSaveProps } from '@kbn/saved-objects-plugin/public/save_modal'; import { act } from 'react-dom/test-utils'; import { inspectorPluginMock } from '@kbn/inspector-plugin/public/mocks'; import { Visualization } from '../types'; +import { createMockDatasource, createMockVisualization } from '../mocks'; jest.mock('@kbn/inspector-plugin/public', () => ({ isAvailable: false, open: false, })); +const defaultVisualizationId = 'lnsSomeVisType'; +const defaultDatasourceId = 'someDatasource'; + const savedVis: Document = { state: { - visualization: {}, - datasourceStates: {}, + visualization: { activeId: defaultVisualizationId }, + datasourceStates: { [defaultDatasourceId]: {} }, query: { query: '', language: 'lucene' }, filters: [], }, references: [], title: 'My title', - visualizationType: '', + visualizationType: defaultVisualizationId, +}; + +const defaultVisualizationMap = { + [defaultVisualizationId]: createMockVisualization(), +}; + +const defaultDatasourceMap = { + [defaultDatasourceId]: createMockDatasource(defaultDatasourceId), }; + const defaultSaveMethod = ( testAttributes: LensSavedObjectAttributes, savedObjectId?: string @@ -155,8 +168,8 @@ describe('embeddable', () => { inspector: inspectorPluginMock.createStartContract(), getTrigger, theme: themeServiceMock.createStartContract(), - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), documentToExpression: () => Promise.resolve({ @@ -208,8 +221,8 @@ describe('embeddable', () => { inspector: inspectorPluginMock.createStartContract(), getTrigger, theme: themeServiceMock.createStartContract(), - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), documentToExpression: () => Promise.resolve({ @@ -268,8 +281,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -322,8 +335,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -398,8 +411,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -452,8 +465,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -505,8 +518,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -554,8 +567,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -609,8 +622,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -668,8 +681,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -725,8 +738,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -789,8 +802,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -854,8 +867,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -922,8 +935,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -975,8 +988,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -1030,8 +1043,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -1082,8 +1095,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -1150,8 +1163,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -1236,8 +1249,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -1297,8 +1310,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -1355,8 +1368,8 @@ describe('embeddable', () => { navLinks: {}, }, getTrigger, - visualizationMap: {}, - datasourceMap: {}, + visualizationMap: defaultVisualizationMap, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), theme: themeServiceMock.createStartContract(), documentToExpression: () => @@ -1408,7 +1421,7 @@ describe('embeddable', () => { const visDocument: Document = { state: { visualization: {}, - datasourceStates: {}, + datasourceStates: { [defaultDatasourceId]: {} }, query: { query: '', language: 'lucene' }, filters: [], }, @@ -1443,7 +1456,7 @@ describe('embeddable', () => { initialize: () => {}, } as unknown as Visualization, }, - datasourceMap: {}, + datasourceMap: defaultDatasourceMap, documentToExpression: documentToExpressionMock, }, { id: '123' } as unknown as LensEmbeddableInput @@ -1475,23 +1488,11 @@ describe('embeddable', () => { 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 = (displayOptions?: { noPadding: boolean }, noPadding?: boolean) => { return new Embeddable( { timefilter: dataPluginMock.createSetupContract().query.timefilter.timefilter, - attributeService: attributeServiceMockFromSavedVis(visDocument), + attributeService: attributeServiceMockFromSavedVis(savedVis), data: dataMock, expressionRenderer, coreStart: {} as CoreStart, @@ -1507,12 +1508,12 @@ describe('embeddable', () => { getTrigger, theme: themeServiceMock.createStartContract(), visualizationMap: { - [visDocument.visualizationType as string]: { + [savedVis.visualizationType as string]: { getDisplayOptions: displayOptions ? () => displayOptions : undefined, initialize: () => {}, } as unknown as Visualization, }, - datasourceMap: {}, + datasourceMap: defaultDatasourceMap, injectFilterReferences: jest.fn(mockInjectFilterReferences), documentToExpression: () => Promise.resolve({ diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 1a22222155677..e89e8c61e3185 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -513,25 +513,23 @@ export class Embeddable private loadUserMessages() { const userMessages: UserMessage[] = []; - if (this.activeVisualizationState && this.activeDatasource) { - userMessages.push( - ...getApplicationUserMessages({ - visualizationType: this.savedVis?.visualizationType, - visualization: { - state: this.activeVisualizationState, - activeId: this.activeVisualizationId, - }, - visualizationMap: this.deps.visualizationMap, - activeDatasource: this.activeDatasource, - activeDatasourceState: { state: this.activeDatasourceState }, - dataViews: { - indexPatterns: this.indexPatterns, - indexPatternRefs: this.indexPatternRefs, // TODO - are these actually used? - }, - core: this.deps.coreStart, - }) - ); - } + userMessages.push( + ...getApplicationUserMessages({ + visualizationType: this.savedVis?.visualizationType, + visualization: { + state: this.activeVisualizationState, + activeId: this.activeVisualizationId, + }, + visualizationMap: this.deps.visualizationMap, + activeDatasource: this.activeDatasource, + activeDatasourceState: { state: this.activeDatasourceState }, + dataViews: { + indexPatterns: this.indexPatterns, + indexPatternRefs: this.indexPatternRefs, // TODO - are these actually used? + }, + core: this.deps.coreStart, + }) + ); const mergedSearchContext = this.getMergedSearchContext(); @@ -634,14 +632,18 @@ export class Embeddable savedObjectId: (input as LensByReferenceInput)?.savedObjectId, }; - const { ast, indexPatterns, indexPatternRefs } = await getExpressionFromDocument( - this.savedVis, - this.deps.documentToExpression - ); + try { + const { ast, indexPatterns, indexPatternRefs } = await getExpressionFromDocument( + this.savedVis, + this.deps.documentToExpression + ); - this.expression = ast; - this.indexPatterns = indexPatterns; - this.indexPatternRefs = indexPatternRefs; + this.expression = ast; + this.indexPatterns = indexPatterns; + this.indexPatternRefs = indexPatternRefs; + } catch { + // nothing, errors should be reported via getUserMessages + } if (metaInfo?.sharingSavedObjectProps?.outcome === 'conflict' && !!this.deps.spaces) { this.addUserMessages([ diff --git a/x-pack/test/functional/apps/lens/group3/error_handling.ts b/x-pack/test/functional/apps/lens/group3/error_handling.ts index 85f9cad73992c..997066343509c 100644 --- a/x-pack/test/functional/apps/lens/group3/error_handling.ts +++ b/x-pack/test/functional/apps/lens/group3/error_handling.ts @@ -129,5 +129,27 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'x-pack/test/functional/fixtures/kbn_archiver/lens/missing_fields' ); }); + + it('displays fundamental configuration issues on dashboard', async () => { + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/fundamental_config_errors_on_dashboard' + ); + + await PageObjects.common.navigateToApp('dashboard'); + await PageObjects.dashboard.loadSavedDashboard('lens fundamental config errors dash'); + + const failureElements = await testSubjects.findAll('errorMessageMarkdown'); + const errorMessages = await Promise.all(failureElements.map((el) => el.getVisibleText())); + + expect(errorMessages).to.eql([ + 'Visualization type not found.', + 'The visualization type lnsUNKNOWN could not be resolved.', + 'Could not find datasource for the visualization', + ]); + + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/fundamental_config_errors_on_dashboard' + ); + }); }); } diff --git a/x-pack/test/functional/fixtures/kbn_archiver/lens/fundamental_config_errors_on_dashboard.json b/x-pack/test/functional/fixtures/kbn_archiver/lens/fundamental_config_errors_on_dashboard.json new file mode 100644 index 0000000000000..435c5f43eb1b9 --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/lens/fundamental_config_errors_on_dashboard.json @@ -0,0 +1,9 @@ +{"attributes":{"fieldFormatMap":"{\"hour_of_day\":{}}","name":"Kibana Sample Data Logs","runtimeFieldMap":"{\"hour_of_day\":{\"type\":\"long\",\"script\":{\"source\":\"emit(doc['timestamp'].value.getHour());\"}}}","timeFieldName":"timestamp","title":"kibana_sample_data_logs"},"coreMigrationVersion":"8.8.0","created_at":"2023-02-08T22:00:06.671Z","id":"90943e30-9a47-11e8-b64d-95841ca0b247","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-08T22:00:06.671Z","version":"WzE1MywxXQ=="} + +{"attributes":{"state":{"adHocDataViews":{},"datasourceStates":{"formBased":{"layers":{"19b05f1b-1187-4c55-abe1-a0bfc45d35f7":{"columnOrder":["bf200ba8-e158-41b4-a701-1121910912e9","b39bfe4c-3699-4f11-a211-aa8cf6d19e1c"],"columns":{"b39bfe4c-3699-4f11-a211-aa8cf6d19e1c":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","params":{"emptyAsNull":true},"scale":"ratio","sourceField":"bytes"},"bf200ba8-e158-41b4-a701-1121910912e9":{"dataType":"date","isBucketed":true,"label":"timestamp","operationType":"date_histogram","params":{"dropPartials":false,"includeEmptyRows":true,"interval":"auto"},"scale":"interval","sourceField":"timestamp"}},"incompleteColumns":{},"sampling":1}}},"textBased":{"layers":{}}},"filters":[],"internalReferences":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["b39bfe4c-3699-4f11-a211-aa8cf6d19e1c"],"layerId":"19b05f1b-1187-4c55-abe1-a0bfc45d35f7","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"bf200ba8-e158-41b4-a701-1121910912e9"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"missing visualization type","visualizationType":null},"coreMigrationVersion":"8.8.0","created_at":"2023-02-08T22:00:21.379Z","id":"323d9ca0-a7f8-11ed-a593-e73d16536d96","migrationVersion":{"lens":"8.6.0"},"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-19b05f1b-1187-4c55-abe1-a0bfc45d35f7","type":"index-pattern"}],"type":"lens","updated_at":"2023-02-08T22:00:21.379Z","version":"WzE2NywxXQ=="} + +{"attributes":{"state":{"adHocDataViews":{},"datasourceStates":{"formBased":{"layers":{"19b05f1b-1187-4c55-abe1-a0bfc45d35f7":{"columnOrder":["bf200ba8-e158-41b4-a701-1121910912e9","b39bfe4c-3699-4f11-a211-aa8cf6d19e1c"],"columns":{"b39bfe4c-3699-4f11-a211-aa8cf6d19e1c":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","params":{"emptyAsNull":true},"scale":"ratio","sourceField":"bytes"},"bf200ba8-e158-41b4-a701-1121910912e9":{"dataType":"date","isBucketed":true,"label":"timestamp","operationType":"date_histogram","params":{"dropPartials":false,"includeEmptyRows":true,"interval":"auto"},"scale":"interval","sourceField":"timestamp"}},"incompleteColumns":{},"sampling":1}}},"textBased":{"layers":{}}},"filters":[],"internalReferences":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["b39bfe4c-3699-4f11-a211-aa8cf6d19e1c"],"layerId":"19b05f1b-1187-4c55-abe1-a0bfc45d35f7","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"bf200ba8-e158-41b4-a701-1121910912e9"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"unknown visualization ID","visualizationType":"lnsUNKNOWN"},"coreMigrationVersion":"8.8.0","created_at":"2023-02-08T22:00:21.379Z","id":"40e08f60-a7f8-11ed-a593-e73d16536d96","migrationVersion":{"lens":"8.6.0"},"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-19b05f1b-1187-4c55-abe1-a0bfc45d35f7","type":"index-pattern"}],"type":"lens","updated_at":"2023-02-08T22:00:21.379Z","version":"WzE2OCwxXQ=="} + +{"attributes":{"state":{"adHocDataViews":{},"datasourceStates":{"UNKNOWN":{"layers":{"19b05f1b-1187-4c55-abe1-a0bfc45d35f7":{"columnOrder":["bf200ba8-e158-41b4-a701-1121910912e9","b39bfe4c-3699-4f11-a211-aa8cf6d19e1c"],"columns":{"b39bfe4c-3699-4f11-a211-aa8cf6d19e1c":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","params":{"emptyAsNull":true},"scale":"ratio","sourceField":"bytes"},"bf200ba8-e158-41b4-a701-1121910912e9":{"dataType":"date","isBucketed":true,"label":"timestamp","operationType":"date_histogram","params":{"dropPartials":false,"includeEmptyRows":true,"interval":"auto"},"scale":"interval","sourceField":"timestamp"}},"incompleteColumns":{},"sampling":1}}},"textBased":{"layers":{}}},"filters":[],"internalReferences":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"labelsOrientation":{"x":0,"yLeft":0,"yRight":0},"layers":[{"accessors":["b39bfe4c-3699-4f11-a211-aa8cf6d19e1c"],"layerId":"19b05f1b-1187-4c55-abe1-a0bfc45d35f7","layerType":"data","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"bf200ba8-e158-41b4-a701-1121910912e9"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"unknown datasource ID","visualizationType":"lnsXY"},"coreMigrationVersion":"8.8.0","created_at":"2023-02-08T22:00:21.379Z","id":"49600170-a7f8-11ed-a593-e73d16536d96","migrationVersion":{"lens":"8.6.0"},"references":[{"id":"90943e30-9a47-11e8-b64d-95841ca0b247","name":"indexpattern-datasource-layer-19b05f1b-1187-4c55-abe1-a0bfc45d35f7","type":"index-pattern"}],"type":"lens","updated_at":"2023-02-08T22:00:21.379Z","version":"WzE2OSwxXQ=="} + +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.8.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"56667b2c-e6c4-49f7-9c07-e27e798d7fea\"},\"panelIndex\":\"56667b2c-e6c4-49f7-9c07-e27e798d7fea\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_56667b2c-e6c4-49f7-9c07-e27e798d7fea\"},{\"version\":\"8.8.0\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"802298ec-2195-460c-a6ca-5b0a46271584\"},\"panelIndex\":\"802298ec-2195-460c-a6ca-5b0a46271584\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_802298ec-2195-460c-a6ca-5b0a46271584\"},{\"version\":\"8.8.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"12060b3e-ec82-4c33-9f67-aa713e512211\"},\"panelIndex\":\"12060b3e-ec82-4c33-9f67-aa713e512211\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12060b3e-ec82-4c33-9f67-aa713e512211\"}]","timeRestore":false,"title":"lens fundamental config errors dash","version":1},"coreMigrationVersion":"8.8.0","created_at":"2023-02-08T22:14:41.552Z","id":"674f1f40-a7f8-11ed-a593-e73d16536d96","migrationVersion":{"dashboard":"8.7.0"},"references":[{"id":"323d9ca0-a7f8-11ed-a593-e73d16536d96","name":"56667b2c-e6c4-49f7-9c07-e27e798d7fea:panel_56667b2c-e6c4-49f7-9c07-e27e798d7fea","type":"lens"},{"id":"40e08f60-a7f8-11ed-a593-e73d16536d96","name":"802298ec-2195-460c-a6ca-5b0a46271584:panel_802298ec-2195-460c-a6ca-5b0a46271584","type":"lens"},{"id":"49600170-a7f8-11ed-a593-e73d16536d96","name":"12060b3e-ec82-4c33-9f67-aa713e512211:panel_12060b3e-ec82-4c33-9f67-aa713e512211","type":"lens"}],"type":"dashboard","updated_at":"2023-02-08T22:14:41.552Z","version":"WzI0MCwxXQ=="} \ No newline at end of file From fcc1d48669a7bbaf495a1e2d31a9c61a7aefb414 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Mon, 13 Feb 2023 18:10:45 +0100 Subject: [PATCH 136/203] [Security Solution] integrate CellActions in Events/Alerts DataTables (#149934) issue: https://github.com/elastic/kibana/issues/145666 ## Summary Migrate DataTable component, used to render the alerts/events data grids in different pages: Alerts, Explore pages (Hosts, Users, Network), and also Rule preview. In summary, all data grids but Timeline. The integration won't modify any action or change any functionality, everything is supposed to keep working the same way from the User's perspective. But it has a minor UI update in the actions tooltip layout: *old* ![old](https://user-images.githubusercontent.com/17747913/215819948-9ef23f3f-58b2-4bd5-a9c3-6c365c2e9921.png) *new* ![new](https://user-images.githubusercontent.com/17747913/215820225-9a736bf3-db8d-41e2-86c8-b709ef7a5f66.png) This change was needed since the custom tooltip (old one) was adding too many Security-related customizations to the generic EuiDataGrid's _columnCellActions_, and also it had a lot of "action-specific" complexity, which is against the idea of having an action-agnostic generic component, to begin with. So, in order to unify the CellActions user experience (icon, text, layout...), we needed to use a more uniformed component, that will render all the actions without any special case. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/components/cell_actions.tsx | 9 +- ...use_data_grid_column_cell_actions.test.tsx | 68 +++++--- .../use_data_grid_column_cell_actions.tsx | 97 ++++++++--- .../kbn-cell-actions/src/mocks/helpers.ts | 1 - packages/kbn-cell-actions/src/types.ts | 6 - .../common/types/header_actions/index.ts | 1 - .../common/types/timeline/cells/index.ts | 3 - .../alerts_cell_actions.cy.ts | 130 ++++++++++++++ .../investigate_in_timeline.cy.ts | 39 +---- .../cypress/screens/alerts.ts | 18 ++ .../cypress/screens/alerts_details.ts | 2 +- .../cypress/screens/timeline.ts | 3 +- .../security_solution/cypress/tasks/alerts.ts | 26 ++- .../cypress/tasks/search_bar.ts | 5 +- .../show_top_n/default/show_top_n.test.tsx | 3 - .../actions/show_top_n/default/show_top_n.tsx | 7 +- .../show_top_n/show_top_n_component.test.tsx | 3 - .../transform_control_columns.test.tsx | 1 - .../transform_control_columns.tsx | 1 - .../components/data_table/index.test.tsx | 164 +++++++----------- .../common/components/data_table/index.tsx | 120 ++++++------- .../__snapshots__/index.test.tsx.snap | 9 +- .../events_tab/events_query_tab_body.tsx | 2 - .../components/events_viewer/index.test.tsx | 6 +- .../common/components/events_viewer/index.tsx | 13 +- .../public/common/components/page/index.tsx | 11 +- .../common/lib/cell_actions/constants.ts | 16 -- .../expanded_cell_value_actions.test.tsx | 33 ---- .../expanded_cell_value_actions.tsx | 85 --------- .../data_table/epic_local_storage.test.tsx | 2 - .../components/alerts_table/index.tsx | 3 - .../rules/rule_preview/preview_histogram.tsx | 1 + .../preview_table_cell_renderer.tsx | 2 +- .../render_cell_value.tsx | 2 - .../default_cell_renderer.test.tsx | 36 ---- .../cell_rendering/default_cell_renderer.tsx | 50 ++---- .../page_objects/detections/index.ts | 2 +- 37 files changed, 462 insertions(+), 518 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.ts delete mode 100644 x-pack/plugins/security_solution/public/common/lib/cell_actions/constants.ts delete mode 100644 x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.tsx diff --git a/packages/kbn-cell-actions/src/components/cell_actions.tsx b/packages/kbn-cell-actions/src/components/cell_actions.tsx index 013fc372fcd9e..3d843a3168f79 100644 --- a/packages/kbn-cell-actions/src/components/cell_actions.tsx +++ b/packages/kbn-cell-actions/src/components/cell_actions.tsx @@ -23,14 +23,12 @@ export const CellActions: React.FC = ({ metadata, className, }) => { - const extraContentNodeRef = useRef(null); const nodeRef = useRef(null); const actionContext: CellActionExecutionContext = useMemo( () => ({ field, trigger: { id: triggerId }, - extraContentNodeRef, nodeRef, metadata, }), @@ -49,8 +47,6 @@ export const CellActions: React.FC = ({ > {children} - -

); } @@ -62,16 +58,17 @@ export const CellActions: React.FC = ({ ref={nodeRef} gutterSize="none" justifyContent="flexStart" + className={className} + data-test-subj={dataTestSubj} > {children} - + -

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

); diff --git a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx index db6a02b918ca1..7cb321a6a3f67 100644 --- a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx +++ b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.test.tsx @@ -6,13 +6,14 @@ * Side Public License, v 1. */ -import React, { JSXElementConstructor } from 'react'; +import React, { JSXElementConstructor, MutableRefObject } from 'react'; import { EuiButtonEmpty, EuiDataGridColumnCellActionProps, + EuiDataGridRefProps, type EuiDataGridColumnCellAction, } from '@elastic/eui'; -import { render } from '@testing-library/react'; +import { render, waitFor } from '@testing-library/react'; import { act, renderHook } from '@testing-library/react-hooks'; import { makeAction } from '../mocks/helpers'; import { @@ -35,10 +36,14 @@ const field1 = { name: 'column1', values: ['0.0', '0.1', '0.2', '0.3'], type: 't const field2 = { name: 'column2', values: ['1.0', '1.1', '1.2', '1.3'], type: 'keyword' }; const columns = [{ id: field1.name }, { id: field2.name }]; +const mockCloseCellPopover = jest.fn(); const useDataGridColumnsCellActionsProps: UseDataGridColumnsCellActionsProps = { fields: [field1, field2], triggerId: 'testTriggerId', metadata: { some: 'value' }, + dataGridRef: { + current: { closeCellPopover: mockCloseCellPopover }, + } as unknown as MutableRefObject, }; const renderCellAction = ( @@ -115,7 +120,9 @@ describe('useDataGridColumnsCellActions', () => { cellAction.getByTestId(`dataGridColumnCellAction-${action1.id}`).click(); - expect(action1.execute).toHaveBeenCalled(); + waitFor(() => { + expect(action1.execute).toHaveBeenCalled(); + }); }); it('should execute the action with correct context', async () => { @@ -128,23 +135,27 @@ describe('useDataGridColumnsCellActions', () => { cellAction1.getByTestId(`dataGridColumnCellAction-${action1.id}`).click(); - expect(action1.execute).toHaveBeenCalledWith( - expect.objectContaining({ - field: { name: field1.name, type: field1.type, value: field1.values[1] }, - trigger: { id: useDataGridColumnsCellActionsProps.triggerId }, - }) - ); + await waitFor(() => { + expect(action1.execute).toHaveBeenCalledWith( + expect.objectContaining({ + field: { name: field1.name, type: field1.type, value: field1.values[1] }, + trigger: { id: useDataGridColumnsCellActionsProps.triggerId }, + }) + ); + }); const cellAction2 = renderCellAction(result.current[1][1], { rowIndex: 2 }); cellAction2.getByTestId(`dataGridColumnCellAction-${action2.id}`).click(); - expect(action2.execute).toHaveBeenCalledWith( - expect.objectContaining({ - field: { name: field2.name, type: field2.type, value: field2.values[2] }, - trigger: { id: useDataGridColumnsCellActionsProps.triggerId }, - }) - ); + await waitFor(() => { + expect(action2.execute).toHaveBeenCalledWith( + expect.objectContaining({ + field: { name: field2.name, type: field2.type, value: field2.values[2] }, + trigger: { id: useDataGridColumnsCellActionsProps.triggerId }, + }) + ); + }); }); it('should execute the action with correct page value', async () => { @@ -157,10 +168,27 @@ describe('useDataGridColumnsCellActions', () => { cellAction.getByTestId(`dataGridColumnCellAction-${action1.id}`).click(); - expect(action1.execute).toHaveBeenCalledWith( - expect.objectContaining({ - field: { name: field1.name, type: field1.type, value: field1.values[1] }, - }) - ); + await waitFor(() => { + expect(action1.execute).toHaveBeenCalledWith( + expect.objectContaining({ + field: { name: field1.name, type: field1.type, value: field1.values[1] }, + }) + ); + }); + }); + + it('should close popover then action executed', async () => { + const { result, waitForNextUpdate } = renderHook(useDataGridColumnsCellActions, { + initialProps: useDataGridColumnsCellActionsProps, + }); + await waitForNextUpdate(); + + const cellAction = renderCellAction(result.current[0][0], { rowIndex: 25 }); + + cellAction.getByTestId(`dataGridColumnCellAction-${action1.id}`).click(); + + await waitFor(() => { + expect(mockCloseCellPopover).toHaveBeenCalled(); + }); }); }); diff --git a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx index 0c78561909fc0..2fe9668097f1b 100644 --- a/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx +++ b/packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx @@ -6,8 +6,12 @@ * Side Public License, v 1. */ -import React, { useMemo, useRef } from 'react'; -import { EuiLoadingSpinner, type EuiDataGridColumnCellAction } from '@elastic/eui'; +import React, { MutableRefObject, useCallback, useMemo, useRef } from 'react'; +import { + EuiDataGridRefProps, + EuiLoadingSpinner, + type EuiDataGridColumnCellAction, +} from '@elastic/eui'; import type { CellAction, CellActionCompatibilityContext, @@ -27,11 +31,13 @@ interface BulkField extends Pick { export interface UseDataGridColumnsCellActionsProps extends Pick { fields: BulkField[]; + dataGridRef: MutableRefObject; } export const useDataGridColumnsCellActions = ({ fields, triggerId, metadata, + dataGridRef, disabledActions = [], }: UseDataGridColumnsCellActionsProps): EuiDataGridColumnCellAction[][] => { const bulkContexts: CellActionCompatibilityContext[] = useMemo( @@ -57,15 +63,22 @@ export const useDataGridColumnsCellActions = ({ } return columnsActions.map((actions, columnIndex) => actions.map((action) => - createColumnCellAction({ action, metadata, triggerId, field: fields[columnIndex] }) + createColumnCellAction({ + action, + metadata, + triggerId, + field: fields[columnIndex], + dataGridRef, + }) ) ); - }, [columnsActions, fields, loading, metadata, triggerId]); + }, [columnsActions, fields, loading, metadata, triggerId, dataGridRef]); return columnsCellActions; }; -interface CreateColumnCellActionParams extends Pick { +interface CreateColumnCellActionParams + extends Pick { field: BulkField; action: CellAction; } @@ -74,36 +87,76 @@ const createColumnCellAction = ({ action, metadata, triggerId, + dataGridRef, }: CreateColumnCellActionParams): EuiDataGridColumnCellAction => - function ColumnCellAction({ Component, rowIndex }) { + function ColumnCellAction({ Component, rowIndex, isExpanded }) { const nodeRef = useRef(null); - const extraContentNodeRef = useRef(null); + const buttonRef = useRef(null); - const { name, type, values } = field; - // rowIndex refers to all pages, we need to use the row index relative to the page to get the value - const value = values[rowIndex % values.length]; + const actionContext: CellActionExecutionContext = useMemo(() => { + const { name, type, values } = field; + // rowIndex refers to all pages, we need to use the row index relative to the page to get the value + const value = values[rowIndex % values.length]; + return { + field: { name, type, value }, + trigger: { id: triggerId }, + nodeRef, + metadata, + }; + }, [rowIndex]); - const actionContext: CellActionExecutionContext = { - field: { name, type, value }, - trigger: { id: triggerId }, - extraContentNodeRef, - nodeRef, - metadata, - }; + const onClick = useCallback(async () => { + actionContext.nodeRef.current = await closeAndGetCellElement({ + dataGrid: dataGridRef.current, + isExpanded, + buttonRef, + }); + action.execute(actionContext); + }, [actionContext, isExpanded]); return ( { - action.execute(actionContext); - }} + onClick={onClick} > {action.getDisplayName(actionContext)} -
); }; + +const closeAndGetCellElement = ({ + dataGrid, + isExpanded, + buttonRef, +}: { + dataGrid?: EuiDataGridRefProps | null; + isExpanded: boolean; + buttonRef: MutableRefObject; +}): Promise => + new Promise((resolve) => { + const gridCellElement = isExpanded + ? // if actions popover is expanded the button is outside dataGrid, using euiDataGridRowCell--open class + document.querySelector('div[role="gridcell"].euiDataGridRowCell--open') + : // if not expanded the button is inside the cell, get the parent cell from the button + getParentCellElement(buttonRef.current); + // close the popover if needed + dataGrid?.closeCellPopover(); + // closing the popover updates the cell content, get the first child after all updates + setTimeout(() => { + resolve((gridCellElement?.firstElementChild as HTMLElement) ?? null); + }); + }); + +const getParentCellElement = (element?: HTMLElement | null): HTMLElement | null => { + if (element == null) { + return null; + } + if (element.nodeName === 'div' && element.getAttribute('role') === 'gridcell') { + return element; + } + return getParentCellElement(element.parentElement); +}; diff --git a/packages/kbn-cell-actions/src/mocks/helpers.ts b/packages/kbn-cell-actions/src/mocks/helpers.ts index 75e4399199815..acb1afd1bc21e 100644 --- a/packages/kbn-cell-actions/src/mocks/helpers.ts +++ b/packages/kbn-cell-actions/src/mocks/helpers.ts @@ -32,7 +32,6 @@ export const makeActionContext = ( type: 'keyword', value: 'some value', }, - extraContentNodeRef: {} as MutableRefObject, nodeRef: {} as MutableRefObject, ...override, }); diff --git a/packages/kbn-cell-actions/src/types.ts b/packages/kbn-cell-actions/src/types.ts index aaf2f745f7f61..bb58ebdc69f51 100644 --- a/packages/kbn-cell-actions/src/types.ts +++ b/packages/kbn-cell-actions/src/types.ts @@ -95,16 +95,10 @@ type Metadata = Record | undefined; export interface CellActionExecutionContext extends ActionExecutionContext { field: CellActionField; - /** - * Ref to a DOM node where the action can add custom HTML. - */ - extraContentNodeRef: React.MutableRefObject; - /** * Ref to the node where the cell action are rendered. */ nodeRef: React.MutableRefObject; - /** * Extra configurations for actions. */ diff --git a/x-pack/plugins/security_solution/common/types/header_actions/index.ts b/x-pack/plugins/security_solution/common/types/header_actions/index.ts index 6c533736bf150..0cb080ee23db1 100644 --- a/x-pack/plugins/security_solution/common/types/header_actions/index.ts +++ b/x-pack/plugins/security_solution/common/types/header_actions/index.ts @@ -83,7 +83,6 @@ export type ColumnHeaderOptions = Pick< | 'isResizable' > & { aggregatable?: boolean; - dataTableCellActions?: DataTableCellAction[]; category?: string; columnHeaderType: ColumnHeaderType; description?: string | null; diff --git a/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts b/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts index f5ca9b28628e1..134b659116ee0 100644 --- a/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts +++ b/x-pack/plugins/security_solution/common/types/timeline/cells/index.ts @@ -6,7 +6,6 @@ */ import type { EuiDataGridCellValueElementProps } from '@elastic/eui'; -import type { Filter } from '@kbn/es-query'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import type { ColumnHeaderOptions, RowRenderer } from '../..'; import type { BrowserFields, TimelineNonEcsData } from '../../../search_strategy'; @@ -18,7 +17,6 @@ export type CellValueElementProps = EuiDataGridCellValueElementProps & { data: TimelineNonEcsData[]; ecsData?: Ecs; eventId: string; // _id - globalFilters?: Filter[]; header: ColumnHeaderOptions; isDraggable: boolean; isTimeline?: boolean; // Default cell renderer is used for both the alert table and timeline. This allows us to cheaply separate concerns @@ -30,5 +28,4 @@ export type CellValueElementProps = EuiDataGridCellValueElementProps & { truncate?: boolean; key?: string; closeCellPopover?: () => void; - enableActions?: boolean; }; diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.ts new file mode 100644 index 0000000000000..b322a87929d52 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/alerts_cell_actions.cy.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 { getNewRule } from '../../objects/rule'; +import { CELL_COPY_BUTTON, FILTER_BADGE, SHOW_TOP_N_HEADER } from '../../screens/alerts'; +import { + ALERT_TABLE_FILE_NAME_HEADER, + ALERT_TABLE_FILE_NAME_VALUES, + ALERT_TABLE_SEVERITY_VALUES, + PROVIDER_BADGE, +} from '../../screens/timeline'; + +import { + scrollAlertTableColumnIntoView, + addAlertPropertyToTimeline, + filterForAlertProperty, + showTopNAlertProperty, + clickExpandActions, +} from '../../tasks/alerts'; +import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; +import { cleanKibana } from '../../tasks/common'; +import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; +import { login, visit } from '../../tasks/login'; +import { fillAddFilterForm, openAddFilterPopover } from '../../tasks/search_bar'; +import { openActiveTimeline } from '../../tasks/timeline'; + +import { ALERTS_URL } from '../../urls/navigation'; +describe('Alerts cell actions', () => { + before(() => { + cleanKibana(); + login(); + }); + + context('Opening alerts', () => { + before(() => { + createCustomRuleEnabled(getNewRule()); + }); + + beforeEach(() => { + visit(ALERTS_URL); + waitForAlertsToPopulate(); + }); + + describe('Filter', () => { + it('should filter for a non-empty property', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then((severityVal) => { + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + filterForAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(FILTER_BADGE) + .first() + .should('have.text', `kibana.alert.severity: ${severityVal}`); + }); + }); + + it('should filter for an empty property', () => { + // add condition to make sure the field is empty + openAddFilterPopover(); + fillAddFilterForm({ key: 'file.name', operator: 'does not exist' }); + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + filterForAlertProperty(ALERT_TABLE_FILE_NAME_VALUES, 0); + cy.get(FILTER_BADGE).first().should('have.text', 'NOT file.name: exists'); + }); + }); + + describe('Add to timeline', () => { + it('should add a non-empty property to default timeline', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then((severityVal) => { + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + addAlertPropertyToTimeline(ALERT_TABLE_SEVERITY_VALUES, 0); + openActiveTimeline(); + cy.get(PROVIDER_BADGE) + .first() + .should('have.text', `kibana.alert.severity: "${severityVal}"`); + }); + }); + + it('should add an empty property to default timeline', () => { + // add condition to make sure the field is empty + openAddFilterPopover(); + fillAddFilterForm({ key: 'file.name', operator: 'does not exist' }); + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + addAlertPropertyToTimeline(ALERT_TABLE_FILE_NAME_VALUES, 0); + openActiveTimeline(); + cy.get(PROVIDER_BADGE).first().should('have.text', 'NOT file.name exists'); + }); + }); + + describe('Show Top N', () => { + it('should show top for a property', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then(() => { + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + showTopNAlertProperty(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(SHOW_TOP_N_HEADER).first().should('have.text', `Top kibana.alert.severity`); + }); + }); + }); + + describe('Copy to clipboard', () => { + it('should copy to clipboard', () => { + cy.get(ALERT_TABLE_SEVERITY_VALUES) + .first() + .invoke('text') + .then(() => { + scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); + cy.window().then((win) => { + cy.stub(win, 'prompt').returns('DISABLED WINDOW PROMPT'); + }); + clickExpandActions(ALERT_TABLE_SEVERITY_VALUES, 0); + cy.get(CELL_COPY_BUTTON).should('exist'); + // We are not able to test the "copy to clipboard" action execution + // due to browsers security limitation accessing the clipboard services. + // We assume external `copy` library works + }); + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts index 9095b5d83f4ff..5f52041e75d17 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_alerts/investigate_in_timeline.cy.ts @@ -6,26 +6,15 @@ */ import { getNewRule } from '../../objects/rule'; -import { - ALERT_TABLE_FILE_NAME_HEADER, - ALERT_TABLE_FILE_NAME_VALUES, - ALERT_TABLE_SEVERITY_VALUES, - PROVIDER_BADGE, -} from '../../screens/timeline'; +import { PROVIDER_BADGE } from '../../screens/timeline'; -import { - addAlertPropertyToTimeline, - investigateFirstAlertInTimeline, - scrollAlertTableColumnIntoView, -} from '../../tasks/alerts'; +import { investigateFirstAlertInTimeline } from '../../tasks/alerts'; import { createCustomRuleEnabled } from '../../tasks/api_calls/rules'; import { cleanKibana } from '../../tasks/common'; import { waitForAlertsToPopulate } from '../../tasks/create_new_rule'; import { login, visit } from '../../tasks/login'; -import { openActiveTimeline } from '../../tasks/timeline'; import { ALERTS_URL } from '../../urls/navigation'; -import { fillAddFilterForm, openAddFilterPopover } from '../../tasks/search_bar'; describe('Alerts timeline', () => { before(() => { @@ -48,28 +37,4 @@ describe('Alerts timeline', () => { cy.get(PROVIDER_BADGE).filter(':visible').should('have.text', eventId); }); }); - - it('Add a non-empty property to default timeline', () => { - cy.get(ALERT_TABLE_SEVERITY_VALUES) - .first() - .invoke('text') - .then((severityVal) => { - scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); - addAlertPropertyToTimeline(ALERT_TABLE_SEVERITY_VALUES, 0); - openActiveTimeline(); - cy.get(PROVIDER_BADGE) - .first() - .should('have.text', `kibana.alert.severity: "${severityVal}"`); - }); - }); - - it('Add an empty property to default timeline', () => { - // add condition to make sure the field is empty - openAddFilterPopover(); - fillAddFilterForm({ key: 'file.name', operator: 'does not exist' }); - scrollAlertTableColumnIntoView(ALERT_TABLE_FILE_NAME_HEADER); - addAlertPropertyToTimeline(ALERT_TABLE_FILE_NAME_VALUES, 0); - openActiveTimeline(); - cy.get(PROVIDER_BADGE).first().should('have.text', 'NOT file.name exists'); - }); }); diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 046962a5d9685..1b5ca92e1eb1c 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -134,3 +134,21 @@ export const EVENT_CONTAINER_TABLE_LOADING = '[data-test-subj="events-container- export const EVENT_CONTAINER_TABLE_NOT_LOADING = '[data-test-subj="events-container-loading-false"]'; + +export const FILTER_BADGE = '[data-test-subj^="filter-badge"]'; + +export const CELL_FILTER_IN_BUTTON = + '[data-test-subj="dataGridColumnCellAction-security_filterIn"]'; +export const CELL_FILTER_OUT_BUTTON = + '[data-test-subj="dataGridColumnCellAction-security_filterOut"]'; +export const CELL_ADD_TO_TIMELINE_BUTTON = + '[data-test-subj="dataGridColumnCellAction-security_addToTimeline"]'; +export const CELL_SHOW_TOP_FIELD_BUTTON = + '[data-test-subj="dataGridColumnCellAction-security_showTopN"]'; +export const CELL_COPY_BUTTON = + '[data-test-subj="dataGridColumnCellAction-security_copyToClipboard"]'; + +export const ACTIONS_EXPAND_BUTTON = '[data-test-subj="euiDataGridCellExpandButton"]'; + +export const SHOW_TOP_N_HEADER = + '[data-test-subj="topN-container"] [data-test-subj="header-section-title"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts index 9a1ac0b8d08f1..23b15524305ed 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts_details.ts @@ -50,7 +50,7 @@ export const CELL_EXPAND_VALUE = '[data-test-subj="euiDataGridCellExpandButton"] export const CELL_EXPANSION_POPOVER = '[data-test-subj="euiDataGridExpansionPopover"]'; -export const USER_DETAILS_LINK = '[data-test-subj="data-grid-user-details"]'; +export const USER_DETAILS_LINK = '[data-test-subj="users-link-anchor"]'; export const TABLE_TAB = '[data-test-subj="tableTab"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/timeline.ts b/x-pack/plugins/security_solution/cypress/screens/timeline.ts index 670c709b67bee..a9cdb896cdea4 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timeline.ts @@ -296,7 +296,8 @@ export const ALERT_TABLE_FILE_NAME_HEADER = '[data-gridcell-column-id="file.name export const ALERT_TABLE_FILE_NAME_VALUES = '[data-gridcell-column-id="file.name"][data-test-subj="dataGridRowCell"]'; // empty column for the test data -export const ALERT_TABLE_CELL_ACTIONS_ADD_TO_TIMELINE = '[data-test-subj="add-to-timeline"]'; +export const ALERT_TABLE_CELL_ACTIONS_ADD_TO_TIMELINE = + '[data-test-subj="dataGridColumnCellAction-security_addToTimeline"]'; export const ACTIVE_TIMELINE_BOTTOM_BAR = '[data-test-subj="flyoutBottomBar"] .active-timeline-button'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index c7810db6ae21d..a17d4bb004671 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -32,12 +32,13 @@ import { CLOSED_ALERTS_FILTER_BTN, OPENED_ALERTS_FILTER_BTN, ACKNOWLEDGED_ALERTS_FILTER_BTN, + CELL_ADD_TO_TIMELINE_BUTTON, + CELL_FILTER_IN_BUTTON, + CELL_SHOW_TOP_FIELD_BUTTON, + ACTIONS_EXPAND_BUTTON, } from '../screens/alerts'; import { LOADING_INDICATOR, REFRESH_BUTTON } from '../screens/security_header'; -import { - ALERT_TABLE_CELL_ACTIONS_ADD_TO_TIMELINE, - TIMELINE_COLUMN_SPINNER, -} from '../screens/timeline'; +import { TIMELINE_COLUMN_SPINNER } from '../screens/timeline'; import { UPDATE_ENRICHMENT_RANGE_BUTTON, ENRICHMENT_QUERY_END_INPUT, @@ -299,9 +300,22 @@ export const openAnalyzerForFirstAlertInTimeline = () => { cy.get(OPEN_ANALYZER_BTN).first().click({ force: true }); }; -export const addAlertPropertyToTimeline = (propertySelector: string, rowIndex: number) => { +const clickAction = (propertySelector: string, rowIndex: number, actionSelector: string) => { cy.get(propertySelector).eq(rowIndex).trigger('mouseover'); - cy.get(ALERT_TABLE_CELL_ACTIONS_ADD_TO_TIMELINE).first().click({ force: true }); + cy.get(actionSelector).first().click({ force: true }); +}; +export const clickExpandActions = (propertySelector: string, rowIndex: number) => { + clickAction(propertySelector, rowIndex, ACTIONS_EXPAND_BUTTON); +}; +export const addAlertPropertyToTimeline = (propertySelector: string, rowIndex: number) => { + clickAction(propertySelector, rowIndex, CELL_ADD_TO_TIMELINE_BUTTON); +}; +export const filterForAlertProperty = (propertySelector: string, rowIndex: number) => { + clickAction(propertySelector, rowIndex, CELL_FILTER_IN_BUTTON); +}; +export const showTopNAlertProperty = (propertySelector: string, rowIndex: number) => { + clickExpandActions(propertySelector, rowIndex); + cy.get(CELL_SHOW_TOP_FIELD_BUTTON).first().click({ force: true }); }; export const waitForAlerts = () => { diff --git a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts index fb5e978befdda..fa3dbbc2589e5 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/search_bar.ts @@ -14,7 +14,6 @@ import { ADD_FILTER_FORM_FIELD_INPUT, ADD_FILTER_FORM_OPERATOR_OPTION_IS, ADD_FILTER_FORM_OPERATOR_FIELD, - ADD_FILTER_FORM_FIELD_OPTION, ADD_FILTER_FORM_FILTER_VALUE_INPUT, GLOBAL_KQL_INPUT, } from '../screens/search_bar'; @@ -38,9 +37,7 @@ export const fillKqlQueryBar = (query: string) => { export const fillAddFilterForm = ({ key, value, operator }: SearchBarFilter) => { cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('exist'); cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('be.visible'); - cy.get(ADD_FILTER_FORM_FIELD_INPUT).type(`${key}{downarrow}`); - cy.get(ADD_FILTER_FORM_FIELD_INPUT).click(); - cy.get(ADD_FILTER_FORM_FIELD_OPTION(key)).click({ force: true }); + cy.get(ADD_FILTER_FORM_FIELD_INPUT).type(`${key}{downarrow}{enter}`); if (!operator) { cy.get(ADD_FILTER_FORM_OPERATOR_FIELD).click(); cy.get(ADD_FILTER_FORM_OPERATOR_OPTION_IS).click(); diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.test.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.test.tsx index 26b7ab8e5c052..a2e047bc5e415 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.test.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.test.tsx @@ -53,9 +53,6 @@ describe('createShowTopNAction', () => { const context = { field: { name: 'user.name', value: 'the-value', type: 'keyword', aggregatable: true }, trigger: { id: 'trigger' }, - extraContentNodeRef: { - current: element, - }, nodeRef: { current: element, }, diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.tsx index 4ff35bea5118c..215033409a46f 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/default/show_top_n.tsx @@ -68,11 +68,14 @@ export const createShowTopNAction = ({ !UNSUPPORTED_FIELD_TYPES.includes(field.type) && !!field.aggregatable, execute: async (context) => { - const node = context.extraContentNodeRef?.current; - if (!node) return; + if (!context.nodeRef.current) return; + + const node = document.createElement('div'); + document.body.appendChild(node); const onClose = () => { unmountComponentAtNode(node); + document.body.removeChild(node); }; const element = ( diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.tsx index 49ddc83563fd7..1737a65596a78 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/show_top_n_component.test.tsx @@ -35,9 +35,6 @@ const context = { nodeRef: { current: element, }, - extraContentNodeRef: { - current: null, - }, } as CellActionExecutionContext; describe('TopNAction', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.test.tsx b/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.test.tsx index eb0c2379ff609..e4596cd1fb7f3 100644 --- a/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.test.tsx @@ -19,7 +19,6 @@ describe('transformControlColumns', () => { setEventsDeleted: jest.fn(), columnHeaders: [], controlColumns: [], - disabledCellActions: [], selectedEventIds: {}, tabType: '', isSelectAllChecked: false, diff --git a/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.tsx b/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.tsx index 94980890d1530..651310755b183 100644 --- a/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.tsx +++ b/x-pack/plugins/security_solution/public/common/components/control_columns/transform_control_columns.tsx @@ -34,7 +34,6 @@ export interface TransformColumnsProps { columnHeaders: ColumnHeaderOptions[]; controlColumns: ControlColumnProps[]; data: TimelineItem[]; - disabledCellActions: string[]; fieldBrowserOptions?: FieldBrowserOptions; loadingEventIds: string[]; onRowSelected: OnRowSelected; diff --git a/x-pack/plugins/security_solution/public/common/components/data_table/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/data_table/index.test.tsx index b4110c1e78340..527eb6e3d0ab9 100644 --- a/x-pack/plugins/security_solution/public/common/components/data_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/data_table/index.test.tsx @@ -14,21 +14,32 @@ import { REMOVE_COLUMN } from './column_headers/translations'; import { useMountAppended } from '../../utils/use_mount_appended'; import type { EuiDataGridColumn } from '@elastic/eui'; import { defaultHeaders, mockGlobalState, mockTimelineData, TestProviders } from '../../mock'; -import { defaultColumnHeaderType } from '../../store/data_table/defaults'; import { mockBrowserFields } from '../../containers/source/mock'; import { getMappedNonEcsValue } from '../../../timelines/components/timeline/body/data_driven_columns'; import type { CellValueElementProps } from '../../../../common/types'; import { TableId } from '../../../../common/types'; +import { CELL_ACTIONS_DEFAULT_TRIGGER } from '../../../../common/constants'; const mockDispatch = jest.fn(); -jest.mock('react-redux', () => { - const original = jest.requireActual('react-redux'); +jest.mock('react-redux', () => ({ + ...jest.requireActual('react-redux'), + useDispatch: () => mockDispatch, +})); - return { - ...original, - useDispatch: () => mockDispatch, - }; -}); +const mockUseDataGridColumnsCellActions = jest.fn( + (_: object): Array JSX.Element>> => [] +); +jest.mock('@kbn/cell-actions', () => ({ + ...jest.requireActual('@kbn/cell-actions'), + useDataGridColumnsCellActions: (params: object) => mockUseDataGridColumnsCellActions(params), +})); + +const headersJustTimestamp = defaultHeaders.filter((h) => h.id === '@timestamp'); +const mockGetColumnHeaders = jest.fn(() => headersJustTimestamp); +jest.mock('./column_headers/helpers', () => ({ + ...jest.requireActual('./column_headers/helpers'), + getColumnHeaders: () => mockGetColumnHeaders(), +})); jest.mock('@kbn/kibana-react-plugin/public', () => { const originalModule = jest.requireActual('@kbn/kibana-react-plugin/public'); @@ -80,8 +91,6 @@ describe('DataTable', () => { const props: DataTableProps = { browserFields: mockBrowserFields, data: mockTimelineData, - defaultCellActions: [], - disabledCellActions: ['signal.rule.risk_score', 'signal.reason'], id: TableId.test, loadPage: jest.fn(), renderCellValue: TestCellRenderer, @@ -98,7 +107,8 @@ describe('DataTable', () => { }; beforeEach(() => { - mockDispatch.mockReset(); + mockDispatch.mockClear(); + mockUseDataGridColumnsCellActions.mockClear(); }); describe('rendering', () => { @@ -142,10 +152,8 @@ describe('DataTable', () => { }); test('it renders cell value', () => { - const headersJustTimestamp = defaultHeaders.filter((h) => h.id === '@timestamp'); const testProps = { ...props, - columnHeaders: headersJustTimestamp, data: mockTimelineData.slice(0, 1), }; const wrapper = mount( @@ -163,49 +171,55 @@ describe('DataTable', () => { .text() ).toEqual(mockTimelineData[0].ecs.timestamp); }); + }); - test('timestamp column renders cell actions', () => { - const headersJustTimestamp = defaultHeaders.filter((h) => h.id === '@timestamp'); - const testProps = { - ...props, - columnHeaders: headersJustTimestamp, - data: mockTimelineData.slice(0, 1), - }; + describe('cellActions', () => { + test('calls useDataGridColumnsCellActions properly', () => { + const data = mockTimelineData.slice(0, 1); const wrapper = mount( - + ); wrapper.update(); - expect( - wrapper - .find('[data-test-subj="body-data-grid"]') - .first() - .prop('columns') - .find((c) => c.id === '@timestamp')?.cellActions - ).toBeDefined(); + expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith({ + triggerId: CELL_ACTIONS_DEFAULT_TRIGGER, + fields: [ + { + name: '@timestamp', + values: [data[0]?.data[0]?.value], + type: 'date', + aggregatable: true, + }, + ], + metadata: { + scopeId: 'table-test', + }, + dataGridRef: expect.any(Object), + }); }); - test("signal.rule.risk_score column doesn't render cell actions", () => { - const columnHeaders = [ - { - category: 'signal', - columnHeaderType: defaultColumnHeaderType, - id: 'signal.rule.risk_score', - type: 'number', - aggregatable: true, - initialWidth: 105, - }, - ]; - const testProps = { - ...props, - columnHeaders, - data: mockTimelineData.slice(0, 1), - }; + test('does not render cell actions if disableCellActions is true', () => { const wrapper = mount( - + + + ); + wrapper.update(); + + expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith( + expect.objectContaining({ + fields: [], + }) + ); + }); + + test('does not render cell actions if empty actions returned', () => { + mockUseDataGridColumnsCellActions.mockReturnValueOnce([]); + const wrapper = mount( + + ); wrapper.update(); @@ -215,29 +229,15 @@ describe('DataTable', () => { .find('[data-test-subj="body-data-grid"]') .first() .prop('columns') - .find((c) => c.id === 'signal.rule.risk_score')?.cellActions - ).toBeUndefined(); + .find((c) => c.id === '@timestamp')?.cellActions + ).toHaveLength(0); }); - test("signal.reason column doesn't render cell actions", () => { - const columnHeaders = [ - { - category: 'signal', - columnHeaderType: defaultColumnHeaderType, - id: 'signal.reason', - type: 'string', - aggregatable: true, - initialWidth: 450, - }, - ]; - const testProps = { - ...props, - columnHeaders, - data: mockTimelineData.slice(0, 1), - }; + test('renders returned cell actions', () => { + mockUseDataGridColumnsCellActions.mockReturnValueOnce([[() =>
]]); const wrapper = mount( - + ); wrapper.update(); @@ -247,43 +247,11 @@ describe('DataTable', () => { .find('[data-test-subj="body-data-grid"]') .first() .prop('columns') - .find((c) => c.id === 'signal.reason')?.cellActions - ).toBeUndefined(); + .find((c) => c.id === '@timestamp')?.cellActions + ).toHaveLength(1); }); }); - test("signal.rule.risk_score column doesn't render cell actions", () => { - const columnHeaders = [ - { - category: 'signal', - columnHeaderType: defaultColumnHeaderType, - id: 'signal.rule.risk_score', - type: 'number', - aggregatable: true, - initialWidth: 105, - }, - ]; - const testProps = { - ...props, - columnHeaders, - data: mockTimelineData.slice(0, 1), - }; - const wrapper = mount( - - - - ); - wrapper.update(); - - expect( - wrapper - .find('[data-test-subj="body-data-grid"]') - .first() - .prop('columns') - .find((c) => c.id === 'signal.rule.risk_score')?.cellActions - ).toBeUndefined(); - }); - test('it does NOT render switches for hiding columns in the `EuiDataGrid` `Columns` popover', async () => { render( diff --git a/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx b/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx index 85189cd221b2f..bfddac06f64b5 100644 --- a/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/data_table/index.tsx @@ -22,11 +22,13 @@ import React, { useCallback, useEffect, useMemo, useContext, useRef } from 'reac import { useDispatch } from 'react-redux'; import styled, { ThemeContext } from 'styled-components'; -import type { Filter } from '@kbn/es-query'; import type { EuiTheme } from '@kbn/kibana-react-plugin/common'; import type { FieldBrowserOptions } from '@kbn/triggers-actions-ui-plugin/public'; import { i18n } from '@kbn/i18n'; -import type { DataTableCellAction } from '../../../../common/types'; +import { + useDataGridColumnsCellActions, + type UseDataGridColumnsCellActionsProps, +} from '@kbn/cell-actions'; import type { CellValueElementProps, ColumnHeaderOptions, @@ -36,12 +38,7 @@ import type { import type { TimelineItem } from '../../../../common/search_strategy/timeline'; import { getColumnHeader, getColumnHeaders } from './column_headers/helpers'; -import { - addBuildingBlockStyle, - hasCellActions, - mapSortDirectionToDirection, - mapSortingColumns, -} from './helpers'; +import { addBuildingBlockStyle, mapSortDirectionToDirection, mapSortingColumns } from './helpers'; import type { BrowserFields } from '../../../../common/search_strategy/index_fields'; import { REMOVE_COLUMN } from './column_headers/translations'; @@ -52,6 +49,7 @@ import { getPageRowIndex } from './pagination'; import { UnitCount } from '../toolbar/unit'; import { useShallowEqualSelector } from '../../hooks/use_selector'; import { tableDefaults } from '../../store/data_table/defaults'; +import { CELL_ACTIONS_DEFAULT_TRIGGER } from '../../../../common/constants'; const DATA_TABLE_ARIA_LABEL = i18n.translate('xpack.securitySolution.dataTable.ariaLabel', { defaultMessage: 'Alerts', @@ -62,10 +60,8 @@ export interface DataTableProps { browserFields: BrowserFields; bulkActions?: BulkActionsProp; data: TimelineItem[]; - defaultCellActions?: DataTableCellAction[]; - disabledCellActions: string[]; + disableCellActions?: boolean; fieldBrowserOptions?: FieldBrowserOptions; - filters?: Filter[]; id: string; leadingControlColumns: EuiDataGridControlColumn[]; loadPage: (newActivePage: number) => void; @@ -107,7 +103,7 @@ const EuiDataGridContainer = styled.div<{ hideLastPage: boolean }>` } `; -const memoizedColumnHeaders: ( +const memoizedGetColumnHeaders: ( headers: ColumnHeaderOptions[], browserFields: BrowserFields, isEventRenderedView: boolean @@ -119,10 +115,8 @@ export const DataTableComponent = React.memo( browserFields, bulkActions = true, data, - defaultCellActions, - disabledCellActions, + disableCellActions = false, fieldBrowserOptions, - filters, hasCrudPermissions, id, leadingControlColumns, @@ -143,7 +137,7 @@ export const DataTableComponent = React.memo( const { columns, selectedEventIds, showCheckboxes, sort, isLoading, defaultColumns } = dataTable; - const columnHeaders = memoizedColumnHeaders(columns, browserFields, isEventRenderedView); + const columnHeaders = memoizedGetColumnHeaders(columns, browserFields, isEventRenderedView); const dataGridRef = useRef(null); @@ -309,57 +303,52 @@ export const DataTableComponent = React.memo( [dispatch, id] ); + const columnsCellActionsProps = useMemo((): UseDataGridColumnsCellActionsProps => { + const fields: UseDataGridColumnsCellActionsProps['fields'] = disableCellActions + ? [] + : columnHeaders.map((column) => ({ + name: column.id, + type: column.type ?? 'keyword', + values: data.map( + ({ data: columnData }) => + columnData.find((rowData) => rowData.field === column.id)?.value + ), + aggregatable: column.aggregatable, + })); + + return { + triggerId: CELL_ACTIONS_DEFAULT_TRIGGER, + fields, + metadata: { + scopeId: id, + }, + dataGridRef, + }; + }, [disableCellActions, columnHeaders, data, id]); + + const columnsCellActions = useDataGridColumnsCellActions(columnsCellActionsProps); + const columnsWithCellActions: EuiDataGridColumn[] = useMemo( () => - columnHeaders.map((header) => { - const buildAction = (dataTableCellAction: DataTableCellAction) => - dataTableCellAction({ - browserFields, - data: data.map((row) => row.data), - ecsData: data.map((row) => row.ecs), - header: columnHeaders.find((h) => h.id === header.id), - pageSize: pagination.pageSize, - scopeId: id, - closeCellPopover: dataGridRef.current?.closeCellPopover, - }); - return { - ...header, - actions: { - ...header.actions, - additional: [ - { - iconType: 'cross', - label: REMOVE_COLUMN, - onClick: () => { - dispatch(dataTableActions.removeColumn({ id, columnId: header.id })); - }, - size: 'xs', + columnHeaders.map((header, columnIndex) => ({ + ...header, + actions: { + ...header.actions, + additional: [ + { + iconType: 'cross', + label: REMOVE_COLUMN, + onClick: () => { + dispatch(dataTableActions.removeColumn({ id, columnId: header.id })); }, - ], - }, - ...(hasCellActions({ - columnId: header.id, - disabledCellActions, - }) - ? { - cellActions: - header.dataTableCellActions?.map(buildAction) ?? - defaultCellActions?.map(buildAction), - visibleCellActions: 3, - } - : {}), - }; - }), - [ - browserFields, - columnHeaders, - data, - defaultCellActions, - disabledCellActions, - dispatch, - id, - pagination.pageSize, - ] + size: 'xs', + }, + ], + }, + cellActions: columnsCellActions[columnIndex] ?? [], + visibleCellActions: 3, + })), + [columnHeaders, columnsCellActions, dispatch, id] ); const renderTableCellValue = useMemo(() => { @@ -392,12 +381,12 @@ export const DataTableComponent = React.memo( } return renderCellValue({ + asPlainText: false, browserFields, columnId: header.id, data: rowData, ecsData: ecs, eventId, - globalFilters: filters, header, isDetails, isDraggable: false, @@ -417,7 +406,6 @@ export const DataTableComponent = React.memo( browserFields, columnHeaders, data, - filters, id, pagination.pageSize, renderCellValue, diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/overview/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/event_details/overview/__snapshots__/index.test.tsx.snap index 23d6db8adf75e..89d876e5efa88 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/overview/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/event_details/overview/__snapshots__/index.test.tsx.snap @@ -116,19 +116,18 @@ exports[`Event Details Overview Cards renders rows and spacers correctly 1`] = ` >
-
@@ -163,19 +162,18 @@ exports[`Event Details Overview Cards renders rows and spacers correctly 1`] = ` >
-
@@ -222,19 +220,18 @@ exports[`Event Details Overview Cards renders rows and spacers correctly 1`] = ` >
-
diff --git a/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx b/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx index a72e0aa35f3ad..af8b54f6f5c90 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_tab/events_query_tab_body.tsx @@ -30,7 +30,6 @@ import { DefaultCellRenderer } from '../../../timelines/components/timeline/cell import { SourcererScopeName } from '../../store/sourcerer/model'; import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; import { DEFAULT_COLUMN_MIN_WIDTH } from '../../../timelines/components/timeline/body/constants'; -import { defaultCellActions } from '../../lib/cell_actions/default_cell_actions'; import type { GlobalTimeArgs } from '../../containers/use_global_time'; import type { QueryTabBodyProps as UserQueryTabBodyProps } from '../../../explore/users/pages/navigation/types'; import type { QueryTabBodyProps as HostQueryTabBodyProps } from '../../../explore/hosts/pages/navigation/types'; @@ -182,7 +181,6 @@ const EventsQueryTabBodyComponent: React.FC = )} void; - renderCellValue: (props: CellValueElementProps) => React.ReactNode; + renderCellValue: React.FC; rowRenderers: RowRenderer[]; additionalFilters?: React.ReactNode; hasCrudPermissions?: boolean; @@ -105,8 +103,8 @@ export interface EventsViewerProps { * NOTE: As of writting, it is not used in the Case_View component */ const StatefulEventsViewerComponent: React.FC = ({ - defaultCellActions, defaultModel, + disableCellActions, end, entityType = 'events', tableId, @@ -441,7 +439,6 @@ const StatefulEventsViewerComponent: React.FC css` SIDE EFFECT: the following `createGlobalStyle` overrides default styling in angular code that was not theme-friendly and `EuiPopover`, `EuiToolTip` global styles */ -export const AppGlobalStyle = createGlobalStyle<{ theme: { eui: { euiColorPrimary: string } } }>` +export const AppGlobalStyle = createGlobalStyle<{ + theme: { eui: { euiColorPrimary: string; euiColorLightShade: string; euiSizeS: string } }; +}>` ${TIMELINE_OVERRIDES_CSS_STYLESHEET} @@ -103,11 +105,16 @@ export const AppGlobalStyle = createGlobalStyle<{ theme: { eui: { euiColorPrimar .euiPopoverFooter { border: 0; - margin-top: 0 !important; + margin-top: 0; .euiFlexGroup { flex-direction: column; } } + + .euiText + .euiPopoverFooter { + border-top: 1px solid ${({ theme }) => theme.eui.euiColorLightShade}; + margin-top: ${({ theme }) => theme.eui.euiSizeS}; + } } /* overrides default styling in angular code that was not theme-friendly */ diff --git a/x-pack/plugins/security_solution/public/common/lib/cell_actions/constants.ts b/x-pack/plugins/security_solution/public/common/lib/cell_actions/constants.ts deleted file mode 100644 index bccd4efa8f98c..0000000000000 --- a/x-pack/plugins/security_solution/public/common/lib/cell_actions/constants.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 { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; - -/** actions are disabled for these fields in tables and popovers */ -export const FIELDS_WITHOUT_CELL_ACTIONS = [ - 'signal.rule.risk_score', - 'signal.reason', - ALERT_RISK_SCORE, - 'kibana.alert.reason', -]; diff --git a/x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.test.tsx b/x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.test.tsx deleted file mode 100644 index e20c4887c0df9..0000000000000 --- a/x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.test.tsx +++ /dev/null @@ -1,33 +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 { shallow } from 'enzyme'; -import React from 'react'; -import { ExpandedCellValueActions } from './expanded_cell_value_actions'; -import type { ColumnHeaderType } from '@kbn/timelines-plugin/common/types'; - -jest.mock('../kibana'); - -describe('ExpandedCellValueActions', () => { - const props = { - field: { - id: 'host.name', - type: 'keyword', - columnHeaderType: 'not-filtered' as ColumnHeaderType, - aggregatable: true, - }, - globalFilters: [], - onFilterAdded: () => {}, - scopeId: 'mockTimelineId', - value: ['mock value'], - }; - const wrapper = shallow(); - - test('renders show topN button', () => { - expect(wrapper.find('[data-test-subj="data-grid-expanded-show-top-n"]').exists()).toBeTruthy(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.tsx b/x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.tsx deleted file mode 100644 index 4d36c450fd177..0000000000000 --- a/x-pack/plugins/security_solution/public/common/lib/cell_actions/expanded_cell_value_actions.tsx +++ /dev/null @@ -1,85 +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 { EuiButtonEmpty } from '@elastic/eui'; -import { noop } from 'lodash/fp'; -import React, { useMemo, useState, useCallback } from 'react'; -import styled from 'styled-components'; -import type { Filter } from '@kbn/es-query'; -import type { ColumnHeaderOptions } from '../../../../common/types'; -import { allowTopN } from '../../components/drag_and_drop/helpers'; -import { ShowTopNButton } from '../../components/hover_actions/actions/show_top_n'; -import { SHOW_TOP_VALUES, HIDE_TOP_VALUES } from './translations'; - -interface Props { - field: ColumnHeaderOptions; - globalFilters?: Filter[]; - scopeId: string; - value: string[] | undefined; - onFilterAdded?: () => void; -} - -const StyledContent = styled.div<{ $isDetails: boolean }>` - border-bottom: 1px solid #d3dae6; - padding: ${({ $isDetails }) => ($isDetails ? '0 8px' : undefined)}; -`; - -const ExpandedCellValueActionsComponent: React.FC = ({ - field, - globalFilters, - onFilterAdded, - scopeId, - value, -}) => { - const showButton = useMemo( - () => - allowTopN({ - fieldName: field.id, - fieldType: field.type ?? '', - isAggregatable: field.aggregatable ?? false, - hideTopN: false, - }), - [field] - ); - - const [showTopN, setShowTopN] = useState(false); - const onClick = useCallback(() => setShowTopN(!showTopN), [showTopN]); - - return ( - <> - - {showButton ? ( - - ) : null} - - - ); -}; - -ExpandedCellValueActionsComponent.displayName = 'ExpandedCellValueActionsComponent'; - -export const ExpandedCellValueActions = React.memo(ExpandedCellValueActionsComponent); diff --git a/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.test.tsx b/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.test.tsx index 4eb160b644904..0ffd6c33aa3ed 100644 --- a/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.test.tsx +++ b/x-pack/plugins/security_solution/public/common/store/data_table/epic_local_storage.test.tsx @@ -40,7 +40,6 @@ import { addTableInStorage } from '../../../timelines/containers/local_storage'; import { Direction } from '../../../../common/search_strategy'; import { StatefulEventsViewer } from '../../components/events_viewer'; import { eventsDefaultModel } from '../../components/events_viewer/default_model'; -import { defaultCellActions } from '../../lib/cell_actions/default_cell_actions'; import { EntityType } from '@kbn/timelines-plugin/common'; import { getDefaultControlColumn } from '../../../timelines/components/timeline/body/control_columns'; import { SourcererScopeName } from '../sourcerer/model'; @@ -64,7 +63,6 @@ describe('epicLocalStorage', () => { const ACTION_BUTTON_COUNT = 4; testProps = { - defaultCellActions, defaultModel: eventsDefaultModel, end: to, entityType: EntityType.ALERTS, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index b6de0e4f80c7b..c191dcf20e98e 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -39,7 +39,6 @@ import { StatefulEventsViewer } from '../../../common/components/events_viewer'; import { useSourcererDataView } from '../../../common/containers/sourcerer'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { useInvalidFilterQuery } from '../../../common/hooks/use_invalid_filter_query'; -import { defaultCellActions } from '../../../common/lib/cell_actions/default_cell_actions'; import { useKibana } from '../../../common/lib/kibana'; import type { inputsModel, State } from '../../../common/store'; import { inputsSelectors } from '../../../common/store'; @@ -416,7 +415,6 @@ export const AlertsTableComponent: React.FC = ({ = ({ = (props) => RenderCellValue({ ...props, enableActions: false, asPlainText: true }); +> = (props) => RenderCellValue({ ...props, asPlainText: true }); diff --git a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.tsx b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.tsx index 21d0d3a199f55..476e15fce02a3 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.tsx +++ b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.tsx @@ -91,7 +91,6 @@ export const useRenderCellValue = ({ data, ecsData, eventId, - globalFilters, header, isDetails = false, isDraggable = false, @@ -120,7 +119,6 @@ export const useRenderCellValue = ({ data={data} ecsData={ecsData} eventId={eventId} - globalFilters={globalFilters} header={myHeader} isDetails={isDetails} isDraggable={isDraggable} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx index 34f57d567951c..3487e2770ff45 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx @@ -127,42 +127,6 @@ describe('DefaultCellRenderer', () => { values: ['2018-11-05T19:03:25.937Z'], }); }); - - test('if in tgrid expanded value, it renders ExpandedCellValueActions', () => { - const data = cloneDeep(mockTimelineData[0].data); - const header = cloneDeep(defaultHeaders[1]); - const isDetails = true; - const id = 'event.severity'; - const wrapper = mount( - - - - - - - - ); - - expect( - wrapper.find('[data-test-subj="data-grid-expanded-cell-value-actions"]').exists() - ).toBeTruthy(); - }); }); describe('host link rendering', () => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.tsx index 1fafa85162ea1..8056a07fb39de 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.tsx @@ -13,12 +13,6 @@ import { columnRenderers } from '../body/renderers'; import { getColumnRenderer } from '../body/renderers/get_column_renderer'; import type { CellValueElementProps } from '.'; import { getLinkColumnDefinition } from '../../../../common/lib/cell_actions/helpers'; -import { FIELDS_WITHOUT_CELL_ACTIONS } from '../../../../common/lib/cell_actions/constants'; -import { ExpandedCellValueActions } from '../../../../common/lib/cell_actions/expanded_cell_value_actions'; - -const hasCellActions = (columnId?: string) => { - return columnId && !FIELDS_WITHOUT_CELL_ACTIONS.includes(columnId); -}; const StyledContent = styled.div<{ $isDetails: boolean }>` padding: ${({ $isDetails }) => ($isDetails ? '0 8px' : undefined)}; @@ -28,7 +22,6 @@ export const DefaultCellRenderer: React.FC = ({ data, ecsData, eventId, - globalFilters, header, isDetails, isDraggable, @@ -37,7 +30,6 @@ export const DefaultCellRenderer: React.FC = ({ rowRenderers, scopeId, truncate, - enableActions = true, asPlainText, }) => { const asPlainTextDefault = useMemo(() => { @@ -54,31 +46,21 @@ export const DefaultCellRenderer: React.FC = ({ ? 'eui-textBreakWord' : 'eui-displayInlineBlock eui-textTruncate'; return ( - <> - - {getColumnRenderer(header.id, columnRenderers, data).renderColumn({ - asPlainText: asPlainText ?? asPlainTextDefault, // we want to render value with links as plain text but keep other formatters like badge. Except rule name for non preview tables - columnName: header.id, - ecsData, - eventId, - field: header, - isDetails, - isDraggable, - linkValues, - rowRenderers, - scopeId, - truncate, - values, - })} - - {enableActions && isDetails && hasCellActions(header.id) && ( - - )} - + + {getColumnRenderer(header.id, columnRenderers, data).renderColumn({ + asPlainText: asPlainText ?? asPlainTextDefault, // we want to render value with links as plain text but keep other formatters like badge. Except rule name for non preview tables + columnName: header.id, + ecsData, + eventId, + field: header, + isDetails, + isDraggable, + linkValues, + rowRenderers, + scopeId, + truncate, + values, + })} + ); }; diff --git a/x-pack/test/security_solution_ftr/page_objects/detections/index.ts b/x-pack/test/security_solution_ftr/page_objects/detections/index.ts index 1b2b6628afe69..e633bd9b62dda 100644 --- a/x-pack/test/security_solution_ftr/page_objects/detections/index.ts +++ b/x-pack/test/security_solution_ftr/page_objects/detections/index.ts @@ -172,7 +172,7 @@ export class DetectionsPageObject extends FtrService { for (const eventRow of allEvents) { const hostNameButton = await this.testSubjects.findDescendant( - 'formatted-field-host.name', + 'host-details-button', eventRow ); const eventRowHostName = (await hostNameButton.getVisibleText()).trim(); From 910bd6e6e0faee30f0fdb0a5f343e87a53135820 Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Mon, 13 Feb 2023 11:21:53 -0600 Subject: [PATCH 137/203] [fleet] add message signing service (#149785) --- .../group2/check_registered_types.test.ts | 1 + .../group3/type_registrations.test.ts | 3 +- .../plugins/fleet/common/constants/index.ts | 1 + .../common/constants/message_signing_keys.ts | 8 + x-pack/plugins/fleet/common/index.ts | 1 + .../plugins/fleet/server/constants/index.ts | 1 + x-pack/plugins/fleet/server/index.ts | 1 + x-pack/plugins/fleet/server/mocks/index.ts | 6 + x-pack/plugins/fleet/server/plugin.ts | 17 +- .../fleet/server/saved_objects/index.ts | 28 ++- .../fleet/server/services/app_context.ts | 7 + x-pack/plugins/fleet/server/services/index.ts | 2 + .../fleet/server/services/security/index.ts | 2 + .../security/message_signing_service.test.ts | 102 ++++++++++ .../security/message_signing_service.ts | 177 ++++++++++++++++++ x-pack/plugins/fleet/server/services/setup.ts | 7 + 16 files changed, 353 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/fleet/common/constants/message_signing_keys.ts create mode 100644 x-pack/plugins/fleet/server/services/security/message_signing_service.test.ts create mode 100644 x-pack/plugins/fleet/server/services/security/message_signing_service.ts diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts index 5558e5156324d..be38a8225d0f4 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_registered_types.test.ts @@ -93,6 +93,7 @@ describe('checking migration metadata changes on all registered SO types', () => "file-upload-usage-collection-telemetry": "c6fcb9a7efcf19b2bb66ca6e005bfee8961f6073", "fileShare": "f07d346acbb724eacf139a0fb781c38dc5280115", "fleet-fleet-server-host": "67180a54a689111fb46403c3603c9b3a329c698d", + "fleet-message-signing-keys": "0c6da6a680807e568540b2aa263ae52331ba66db", "fleet-preconfiguration-deletion-record": "3afad160748b430427086985a3445fd8697566d5", "fleet-proxy": "94d0a902a0fd22578d7d3a20873b95d902e25245", "graph-workspace": "565642a208fe7413b487aea979b5b153e4e74abe", diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts index 2c8dbabf878a1..7f4ca3fb70dc2 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts @@ -58,8 +58,9 @@ const previouslyRegisteredTypes = [ 'fleet-agent-events', 'fleet-agents', 'fleet-enrollment-api-keys', - 'fleet-preconfiguration-deletion-record', 'fleet-fleet-server-host', + 'fleet-message-signing-keys', + 'fleet-preconfiguration-deletion-record', 'fleet-proxy', 'graph-workspace', 'guided-setup-state', diff --git a/x-pack/plugins/fleet/common/constants/index.ts b/x-pack/plugins/fleet/common/constants/index.ts index f42b2a372ebb6..4dcc2d58d65ba 100644 --- a/x-pack/plugins/fleet/common/constants/index.ts +++ b/x-pack/plugins/fleet/common/constants/index.ts @@ -19,6 +19,7 @@ export * from './download_source'; export * from './fleet_server_policy_config'; export * from './authz'; export * from './file_storage'; +export * from './message_signing_keys'; // TODO: This is the default `index.max_result_window` ES setting, which dictates // the maximum amount of results allowed to be returned from a search. It's possible diff --git a/x-pack/plugins/fleet/common/constants/message_signing_keys.ts b/x-pack/plugins/fleet/common/constants/message_signing_keys.ts new file mode 100644 index 0000000000000..a51cff3e376c9 --- /dev/null +++ b/x-pack/plugins/fleet/common/constants/message_signing_keys.ts @@ -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 const MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE = 'fleet-message-signing-keys'; diff --git a/x-pack/plugins/fleet/common/index.ts b/x-pack/plugins/fleet/common/index.ts index 3dc816f9f3090..3cdfa354a8c5f 100644 --- a/x-pack/plugins/fleet/common/index.ts +++ b/x-pack/plugins/fleet/common/index.ts @@ -26,6 +26,7 @@ export { OUTPUT_SAVED_OBJECT_TYPE, PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, ASSETS_SAVED_OBJECT_TYPE, + MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, // Fleet server index FLEET_SERVER_SERVERS_INDEX, FLEET_SERVER_ARTIFACTS_INDEX, diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index 93dc93051e98e..ff7c70d8f64e8 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -44,6 +44,7 @@ export { PACKAGES_SAVED_OBJECT_TYPE, ASSETS_SAVED_OBJECT_TYPE, GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, + MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, // Defaults DEFAULT_OUTPUT, DEFAULT_OUTPUT_ID, diff --git a/x-pack/plugins/fleet/server/index.ts b/x-pack/plugins/fleet/server/index.ts index cfc063cccbeca..b2540552b62be 100644 --- a/x-pack/plugins/fleet/server/index.ts +++ b/x-pack/plugins/fleet/server/index.ts @@ -20,6 +20,7 @@ export type { ArtifactsClientInterface, Artifact, ListArtifactsProps, + MessageSigningServiceInterface, } from './services'; export { getRegistryUrl } from './services'; diff --git a/x-pack/plugins/fleet/server/mocks/index.ts b/x-pack/plugins/fleet/server/mocks/index.ts index d6620fe4c3fb9..75f55a1b353d4 100644 --- a/x-pack/plugins/fleet/server/mocks/index.ts +++ b/x-pack/plugins/fleet/server/mocks/index.ts @@ -58,6 +58,7 @@ export const createAppContextStartContractMock = ( elasticsearch: elasticsearchServiceMock.createStart(), data: dataPluginMock.createStartContract(), encryptedSavedObjectsStart: encryptedSavedObjectsMock.createStart(), + encryptedSavedObjectsSetup: encryptedSavedObjectsMock.createSetup({ canEncrypt: true }), savedObjects: savedObjectsServiceMock.createStartContract(), securitySetup: securityMock.createSetup(), securityStart: securityMock.createStart(), @@ -74,6 +75,11 @@ export const createAppContextStartContractMock = ( kibanaBranch: 'main', telemetryEventsSender: createMockTelemetryEventsSender(), bulkActionsResolver: {} as any, + messageSigningService: { + generateKeyPair: jest.fn(), + sign: jest.fn(), + getPublicKey: jest.fn(), + }, }; }; diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 714ea06d0eefe..265431a87e265 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -54,14 +54,16 @@ import type { FleetConfigType } from '../common/types'; import type { FleetAuthz } from '../common'; import type { ExperimentalFeatures } from '../common/experimental_features'; -import { INTEGRATIONS_PLUGIN_ID } from '../common'; +import { MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, INTEGRATIONS_PLUGIN_ID } from '../common'; import { parseExperimentalConfigValue } from '../common/experimental_features'; +import type { MessageSigningServiceInterface } from './services/security'; import { getRouteRequiredAuthz, makeRouterWithFleetAuthz, calculateRouteAuthz, getAuthzFromRequest, + MessageSigningService, } from './services/security'; import { @@ -151,6 +153,7 @@ export interface FleetAppContext { httpSetup?: HttpServiceSetup; telemetryEventsSender: TelemetryEventsSender; bulkActionsResolver: BulkActionsResolver; + messageSigningService: MessageSigningServiceInterface; } export type FleetSetupContract = void; @@ -198,6 +201,8 @@ export interface FleetStartContract { * @param packageName */ createArtifactsClient: (packageName: string) => FleetArtifactsClient; + + messageSigningService: MessageSigningServiceInterface; } export class FleetPlugin @@ -248,7 +253,7 @@ export class FleetPlugin core.status.set(this.fleetStatus$.asObservable()); - registerSavedObjects(core.savedObjects, deps.encryptedSavedObjects); + registerSavedObjects(core.savedObjects); registerEncryptedSavedObjects(deps.encryptedSavedObjects); // Register feature @@ -422,6 +427,12 @@ export class FleetPlugin } public start(core: CoreStart, plugins: FleetStartDeps): FleetStartContract { + const messageSigningService = new MessageSigningService( + plugins.encryptedSavedObjects.getClient({ + includedHiddenTypes: [MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE], + }) + ); + appContextService.start({ elasticsearch: core.elasticsearch, data: plugins.data, @@ -444,6 +455,7 @@ export class FleetPlugin logger: this.logger, telemetryEventsSender: this.telemetryEventsSender, bulkActionsResolver: this.bulkActionsResolver!, + messageSigningService, }); licenseService.start(plugins.licensing.license$); @@ -530,6 +542,7 @@ export class FleetPlugin createArtifactsClient(packageName: string) { return new FleetArtifactsClient(core.elasticsearch.client.asInternalUser, packageName); }, + messageSigningService, }; } diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 1a8178890b1dc..16480b0031628 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -20,6 +20,7 @@ import { DOWNLOAD_SOURCE_SAVED_OBJECT_TYPE, FLEET_SERVER_HOST_SAVED_OBJECT_TYPE, FLEET_PROXY_SAVED_OBJECT_TYPE, + MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, } from '../constants'; import { @@ -61,9 +62,7 @@ import { migratePackagePolicyToV870 } from './migrations/security_solution'; * Please update typings in `/common/types` as well as * schemas in `/server/types` if mappings are updated. */ -const getSavedObjectTypes = ( - encryptedSavedObjects: EncryptedSavedObjectsPluginSetup -): { [key: string]: SavedObjectsType } => ({ +const getSavedObjectTypes = (): { [key: string]: SavedObjectsType } => ({ // Deprecated [GLOBAL_SETTINGS_SAVED_OBJECT_TYPE]: { name: GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, @@ -366,13 +365,22 @@ const getSavedObjectTypes = ( }, }, }, + [MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE]: { + name: MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, + hidden: true, + namespaceType: 'agnostic', + management: { + importableAndExportable: false, + }, + mappings: { + dynamic: false, + properties: {}, + }, + }, }); -export function registerSavedObjects( - savedObjects: SavedObjectsServiceSetup, - encryptedSavedObjects: EncryptedSavedObjectsPluginSetup -) { - const savedObjectTypes = getSavedObjectTypes(encryptedSavedObjects); +export function registerSavedObjects(savedObjects: SavedObjectsServiceSetup) { + const savedObjectTypes = getSavedObjectTypes(); Object.values(savedObjectTypes).forEach((type) => { savedObjects.registerType(type); }); @@ -400,4 +408,8 @@ export function registerEncryptedSavedObjects( ]), }); // Encrypted saved objects + encryptedSavedObjects.registerType({ + type: MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, + attributesToEncrypt: new Set(['private_key', 'passphrase']), + }); } diff --git a/x-pack/plugins/fleet/server/services/app_context.ts b/x-pack/plugins/fleet/server/services/app_context.ts index c8c6c8b4c0e59..71c09621c59a0 100644 --- a/x-pack/plugins/fleet/server/services/app_context.ts +++ b/x-pack/plugins/fleet/server/services/app_context.ts @@ -43,6 +43,7 @@ import type { } from '../types'; import type { FleetAppContext } from '../plugin'; import type { TelemetryEventsSender } from '../telemetry/sender'; +import type { MessageSigningServiceInterface } from '..'; import type { BulkActionsResolver } from './agents'; @@ -67,6 +68,7 @@ class AppContextService { private telemetryEventsSender: TelemetryEventsSender | undefined; private savedObjectsTagging: SavedObjectTaggingStart | undefined; private bulkActionsResolver: BulkActionsResolver | undefined; + private messageSigningService: MessageSigningServiceInterface | undefined; public start(appContext: FleetAppContext) { this.data = appContext.data; @@ -86,6 +88,7 @@ class AppContextService { this.telemetryEventsSender = appContext.telemetryEventsSender; this.savedObjectsTagging = appContext.savedObjectsTagging; this.bulkActionsResolver = appContext.bulkActionsResolver; + this.messageSigningService = appContext.messageSigningService; if (appContext.config$) { this.config$ = appContext.config$; @@ -243,6 +246,10 @@ class AppContextService { public getBulkActionsResolver() { return this.bulkActionsResolver; } + + public getMessageSigningService() { + return this.messageSigningService; + } } export const appContextService = new AppContextService(); diff --git a/x-pack/plugins/fleet/server/services/index.ts b/x-pack/plugins/fleet/server/services/index.ts index cfd8eb95ceb4d..c2abd872d5df9 100644 --- a/x-pack/plugins/fleet/server/services/index.ts +++ b/x-pack/plugins/fleet/server/services/index.ts @@ -67,3 +67,5 @@ export { migrateSettingsToFleetServerHost } from './fleet_server_host'; export { FleetUsageSender } from './telemetry/fleet_usage_sender'; export { checkAllowedPackages } from './check_allowed_packages'; + +export type { MessageSigningServiceInterface } from './security'; diff --git a/x-pack/plugins/fleet/server/services/security/index.ts b/x-pack/plugins/fleet/server/services/security/index.ts index c41c769c58d8d..6b38c6f6c7d5b 100644 --- a/x-pack/plugins/fleet/server/services/security/index.ts +++ b/x-pack/plugins/fleet/server/services/security/index.ts @@ -15,3 +15,5 @@ export { getAuthzFromRequest, doesNotHaveRequiredFleetAuthz, } from './security'; +export type { MessageSigningServiceInterface } from './message_signing_service'; +export { MessageSigningService } from './message_signing_service'; diff --git a/x-pack/plugins/fleet/server/services/security/message_signing_service.test.ts b/x-pack/plugins/fleet/server/services/security/message_signing_service.test.ts new file mode 100644 index 0000000000000..7416e2af49ec5 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/security/message_signing_service.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. + */ + +import { createVerify } from 'crypto'; + +import type { KibanaRequest } from '@kbn/core-http-server'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server'; + +import { MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE } from '../../constants'; +import { createAppContextStartContractMock } from '../../mocks'; +import { appContextService } from '../app_context'; + +import { + type MessageSigningServiceInterface, + MessageSigningService, +} from './message_signing_service'; + +describe('MessageSigningService', () => { + let soClientMock: jest.Mocked; + let esoClientMock: jest.Mocked; + let messageSigningService: MessageSigningServiceInterface; + const keyPairObj = { + id: 'id1', + type: MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, + attributes: { + private_key: + 'MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgtNcDFoj07+QICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEELajFPDz2bpD2qfPCRHphAgEgZCq0eUxTOEGrefdeNgHR2VVxXjWRZG+cGn+e8LW4auBCwwMiZsAZPKKvzLdlLi5sQhH+qWPM7Z9/OLbF/0ZKvyDM2/+4/9+5Iwna7vueTZtcdSIuGIFRjqUZbgNLejPSPcBMM9SP1V6I8TjDguGAQ3Nj95t7g7cbl0x48nQZ9bNDJyvy4ytHl+ubzdanLlFkLc=', + public_key: + 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6E5aKP8dAa+TlBuSKrrgl9UtkzHjn6YUQO+72vi3khGfUQIpD9qq9MsjsWz6Bvm6tnSOyyPXv+Koh80lNCKw5A==', + passphrase: 'eb35af2291344a51c9a8bb81e653281c38892d564db617a2cb0bc660f0ae96f2', + }, + }; + + function mockCreatePointInTimeFinderAsInternalUser(savedObjects: unknown[] = []) { + esoClientMock.createPointInTimeFinderDecryptedAsInternalUser = jest.fn().mockResolvedValue({ + close: jest.fn(), + find: function* asyncGenerator() { + yield { saved_objects: savedObjects }; + }, + }); + } + + beforeEach(() => { + const mockContext = createAppContextStartContractMock(); + appContextService.start(mockContext); + esoClientMock = + mockContext.encryptedSavedObjectsStart!.getClient() as jest.Mocked; + soClientMock = appContextService + .getSavedObjects() + .getScopedClient({} as unknown as KibanaRequest) as jest.Mocked; + + messageSigningService = new MessageSigningService(esoClientMock); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('can correctly generate key pair if none exist', async () => { + mockCreatePointInTimeFinderAsInternalUser(); + + await messageSigningService.generateKeyPair(); + expect(soClientMock.create).toBeCalledWith(MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, { + private_key: expect.any(String), + public_key: expect.any(String), + passphrase: expect.any(String), + }); + }); + + it('does not generate key pair if one exists', async () => { + mockCreatePointInTimeFinderAsInternalUser([keyPairObj]); + + await messageSigningService.generateKeyPair(); + expect(soClientMock.create).not.toBeCalled(); + }); + + it('can correctly sign messages', async () => { + mockCreatePointInTimeFinderAsInternalUser([keyPairObj]); + + const message = Buffer.from(JSON.stringify({ message: 'foobar' }), 'utf8'); + const { data, signature } = await messageSigningService.sign(message); + + const verifier = createVerify('SHA256'); + verifier.update(data); + verifier.end(); + + const serializedPublicKey = await messageSigningService.getPublicKey(); + const publicKey = Buffer.from(serializedPublicKey, 'base64'); + const isVerified = verifier.verify( + { key: publicKey, format: 'der', type: 'spki' }, + signature, + 'base64' + ); + expect(isVerified).toBe(true); + expect(data).toBe(message); + }); +}); diff --git a/x-pack/plugins/fleet/server/services/security/message_signing_service.ts b/x-pack/plugins/fleet/server/services/security/message_signing_service.ts new file mode 100644 index 0000000000000..6e323a55fc6f8 --- /dev/null +++ b/x-pack/plugins/fleet/server/services/security/message_signing_service.ts @@ -0,0 +1,177 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { generateKeyPairSync, createSign, randomBytes } from 'crypto'; + +import type { KibanaRequest } from '@kbn/core-http-server'; +import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import type { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server'; +import { SECURITY_EXTENSION_ID } from '@kbn/core-saved-objects-server'; + +import { MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE } from '../../constants'; +import { appContextService } from '../app_context'; + +interface MessageSigningKeys { + private_key: string; + public_key: string; + passphrase: string; +} + +export interface MessageSigningServiceInterface { + generateKeyPair(providedPassphrase?: string): Promise; + sign(serializedMessage: Buffer | object): Promise<{ data: Buffer; signature: string }>; + getPublicKey(): Promise; +} + +export class MessageSigningService implements MessageSigningServiceInterface { + private _soClient: SavedObjectsClientContract | undefined; + + constructor(private esoClient: EncryptedSavedObjectsClient) {} + + public async generateKeyPair(providedPassphrase?: string) { + this.checkForEncryptionKey(); + + const currentKeyPair = await this.getCurrentKeyPair(); + if (currentKeyPair.privateKey && currentKeyPair.publicKey && currentKeyPair.passphrase) { + return; + } + + const passphrase = providedPassphrase || this.generatePassphrase(); + + const keyPair = generateKeyPairSync('ec', { + namedCurve: 'prime256v1', + privateKeyEncoding: { + type: 'pkcs8', + format: 'der', + cipher: 'aes-256-cbc', + passphrase, + }, + publicKeyEncoding: { + type: 'spki', + format: 'der', + }, + }); + + await this.soClient.create(MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, { + private_key: keyPair.privateKey.toString('base64'), + public_key: keyPair.publicKey.toString('base64'), + passphrase, + }); + + return; + } + + public async sign( + message: Buffer | Record + ): Promise<{ data: Buffer; signature: string }> { + this.checkForEncryptionKey(); + + const msgBuffer = Buffer.isBuffer(message) + ? message + : Buffer.from(JSON.stringify(message), 'utf8'); + + const signer = createSign('SHA256'); + signer.update(msgBuffer); + signer.end(); + + const { privateKey: serializedPrivateKey, passphrase } = await this.getCurrentKeyPair(); + + if (!serializedPrivateKey) { + throw new Error('unable to find private key'); + } + if (!passphrase) { + throw new Error('unable to find passphrase'); + } + + const privateKey = Buffer.from(serializedPrivateKey, 'base64'); + const signature = signer.sign( + { key: privateKey, passphrase, format: 'der', type: 'pkcs8' }, + 'base64' + ); + return { + data: msgBuffer, + signature, + }; + } + + public async getPublicKey(): Promise { + this.checkForEncryptionKey(); + + const { publicKey } = await this.getCurrentKeyPair(); + + if (!publicKey) { + throw new Error('unable to find public key'); + } + + return publicKey; + } + + private get soClient() { + if (this._soClient) { + return this._soClient; + } + + const fakeRequest = { + headers: {}, + getBasePath: () => '', + path: '/', + route: { settings: {} }, + url: { href: {} }, + raw: { req: { url: '/' } }, + } as unknown as KibanaRequest; + + this._soClient = appContextService.getSavedObjects().getScopedClient(fakeRequest, { + excludedExtensions: [SECURITY_EXTENSION_ID], + includedHiddenTypes: [MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE], + }); + + return this._soClient; + } + + private async getCurrentKeyPair(): Promise<{ + privateKey: string; + publicKey: string; + passphrase: string; + }> { + const finder = + await this.esoClient.createPointInTimeFinderDecryptedAsInternalUser({ + type: MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, + perPage: 1, + sortField: 'created_at', + sortOrder: 'desc', + }); + let keyPair = { + privateKey: '', + publicKey: '', + passphrase: '', + }; + for await (const result of finder.find()) { + const attributes = result.saved_objects[0]?.attributes; + if (!attributes?.private_key) { + break; + } + keyPair = { + privateKey: attributes.private_key, + publicKey: attributes.public_key, + passphrase: attributes.passphrase, + }; + break; + } + + return keyPair; + } + + private generatePassphrase(): string { + return randomBytes(32).toString('hex'); + } + + private checkForEncryptionKey(): void { + if (!appContextService.getEncryptedSavedObjectsSetup()?.canEncrypt) { + throw new Error('encryption key not set, message signing service is disabled'); + } + } +} diff --git a/x-pack/plugins/fleet/server/services/setup.ts b/x-pack/plugins/fleet/server/services/setup.ts index 2802fd34bc001..7acf46408367b 100644 --- a/x-pack/plugins/fleet/server/services/setup.ts +++ b/x-pack/plugins/fleet/server/services/setup.ts @@ -171,6 +171,13 @@ async function createSetupSideEffects( logger.debug('Setting up Fleet enrollment keys'); await ensureDefaultEnrollmentAPIKeysExists(soClient, esClient); + if (appContextService.getEncryptedSavedObjectsSetup()?.canEncrypt) { + logger.debug('Generating key pair for message signing'); + await appContextService.getMessageSigningService()?.generateKeyPair(); + } else { + logger.info('No encryption key set, skipping key pair generation for message signing'); + } + if (nonFatalErrors.length > 0) { logger.info('Encountered non fatal errors during Fleet setup'); formatNonFatalErrors(nonFatalErrors).forEach((error) => logger.info(JSON.stringify(error))); From 1526749ba4793f25549326ca1ff6924cbf2bf885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20R=C3=BChsen?= Date: Mon, 13 Feb 2023 19:15:40 +0100 Subject: [PATCH 138/203] [Profiling] Fix TopN diff functions title text (#151031) Fixes the title texts in the differential TopN functions view (turning 'flamegraph' into 'functions'). Fixes https://github.com/elastic/prodfiler/issues/3000 --- .../primary_and_comparison_search_bar.tsx | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/profiling/public/components/primary_and_comparison_search_bar.tsx b/x-pack/plugins/profiling/public/components/primary_and_comparison_search_bar.tsx index 33f5f3e8850ff..5298d43deacf3 100644 --- a/x-pack/plugins/profiling/public/components/primary_and_comparison_search_bar.tsx +++ b/x-pack/plugins/profiling/public/components/primary_and_comparison_search_bar.tsx @@ -61,15 +61,29 @@ export function PrimaryAndComparisonSearchBar() { } } + let baselineTitle: string; + let comparisonTitle: string; + + if (routePath === '/flamegraphs/differential') { + baselineTitle = i18n.translate('xpack.profiling.comparisonSearch.baselineTitleFlamegraph', { + defaultMessage: 'Baseline flamegraph', + }); + comparisonTitle = i18n.translate('xpack.profiling.comparisonSearch.comparisonTitleFlamegraph', { + defaultMessage: 'Comparison flamegraph', + }); + } else { + baselineTitle = i18n.translate('xpack.profiling.comparisonSearch.baselineTitleFunctions', { + defaultMessage: 'Baseline functions', + }); + comparisonTitle = i18n.translate('xpack.profiling.comparisonSearch.comparisonTitleFunctions', { + defaultMessage: 'Comparison functions', + }); + } return ( -

- {i18n.translate('xpack.profiling.comparisonSearch.baselineTitle', { - defaultMessage: 'Baseline flamegraph', - })} -

+

{baselineTitle}

@@ -107,11 +121,7 @@ export function PrimaryAndComparisonSearchBar() {
-

- {i18n.translate('xpack.profiling.comparisonSearch.comparisonTitle', { - defaultMessage: 'Comparison flamegraph', - })} -

+

{comparisonTitle}

Date: Mon, 13 Feb 2023 18:53:08 +0000 Subject: [PATCH 139/203] [Logs] Fix legacy logFilter handling via the URL (#150902) Fix legacy logFilter handling via the URL --- .../src/url_state_storage_service.ts | 17 +++- x-pack/test/functional/apps/infra/index.ts | 1 + .../test/functional/apps/infra/log_stream.ts | 88 +++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 x-pack/test/functional/apps/infra/log_stream.ts diff --git a/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/url_state_storage_service.ts b/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/url_state_storage_service.ts index c18ee71ed4f8e..fabd26cc03d22 100644 --- a/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/url_state_storage_service.ts +++ b/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/url_state_storage_service.ts @@ -165,11 +165,24 @@ const legacyFilterStateInUrlRT = rt.union([ }), ]); +const legacyLegacyFilterStateWithExpressionInUrlRT = rt.type({ + kind: rt.literal('kuery'), + expression: rt.string, +}); + const decodeQueryValueFromUrl = (queryValueFromUrl: unknown) => Either.getAltValidation(Array.getMonoid()).alt( pipe( - legacyFilterStateInUrlRT.decode(queryValueFromUrl), - Either.map((legacyQuery) => ({ query: legacyQuery })) + pipe( + legacyLegacyFilterStateWithExpressionInUrlRT.decode(queryValueFromUrl), + Either.map(({ expression, kind }) => ({ query: { language: kind, query: expression } })) + ), + Either.alt(() => + pipe( + legacyFilterStateInUrlRT.decode(queryValueFromUrl), + Either.map((legacyQuery) => ({ query: legacyQuery })) + ) + ) ), () => filterStateInUrlRT.decode(queryValueFromUrl) ); diff --git a/x-pack/test/functional/apps/infra/index.ts b/x-pack/test/functional/apps/infra/index.ts index 9e6cb3f74cc96..197481c431394 100644 --- a/x-pack/test/functional/apps/infra/index.ts +++ b/x-pack/test/functional/apps/infra/index.ts @@ -25,6 +25,7 @@ export default ({ loadTestFile }: FtrProviderContext) => { loadTestFile(require.resolve('./log_entry_rate_tab')); loadTestFile(require.resolve('./logs_source_configuration')); loadTestFile(require.resolve('./link_to')); + loadTestFile(require.resolve('./log_stream')); }); }); }; diff --git a/x-pack/test/functional/apps/infra/log_stream.ts b/x-pack/test/functional/apps/infra/log_stream.ts new file mode 100644 index 0000000000000..a0836e4ef57e9 --- /dev/null +++ b/x-pack/test/functional/apps/infra/log_stream.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 expect from '@kbn/expect'; +import { URL } from 'url'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +const SERVICE_ID = '49a18510598271e924253ed2581d7ada'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const pageObjects = getPageObjects(['common']); + const retry = getService('retry'); + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + + describe('Log stream', function () { + describe('Legacy URL handling', async () => { + describe('Correctly handles legacy versions of logFilter', async () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/infra/8.0.0/logs_and_metrics'); + }); + after(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/infra/8.0.0/logs_and_metrics' + ); + }); + it('Expression and kind', async () => { + const location = { + hash: '', + pathname: '/stream', + search: `logFilter=(expression:'service.id:"${SERVICE_ID}"',kind:kuery)`, + state: undefined, + }; + + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'infraLogs', + location.pathname, + location.search, + { + ensureCurrentUrl: false, + } + ); + + await retry.tryForTime(5000, async () => { + const currentUrl = await browser.getCurrentUrl(); + const parsedUrl = new URL(currentUrl); + + expect(parsedUrl.pathname).to.be('/app/logs/stream'); + expect(parsedUrl.searchParams.get('logFilter')).to.be( + `(filters:!(),query:(language:kuery,query:\'service.id:"${SERVICE_ID}"\'))` + ); + }); + }); + it('Top-level query and language', async () => { + const location = { + hash: '', + pathname: '/stream', + search: `logFilter=(query:'service.id:"${SERVICE_ID}"',language:kuery)`, + state: undefined, + }; + + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'infraLogs', + location.pathname, + location.search, + { + ensureCurrentUrl: false, + } + ); + + await retry.tryForTime(5000, async () => { + const currentUrl = await browser.getCurrentUrl(); + const parsedUrl = new URL(currentUrl); + + expect(parsedUrl.pathname).to.be('/app/logs/stream'); + expect(parsedUrl.searchParams.get('logFilter')).to.be( + `(filters:!(),query:(language:kuery,query:\'service.id:"${SERVICE_ID}"\'))` + ); + }); + }); + }); + }); + }); +}; From eb4b92d876376d280c41dc352915e5e6e975cc07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Mon, 13 Feb 2023 14:30:42 -0500 Subject: [PATCH 140/203] [APM] adding API test for alert error count threshold (#150764) Add new api test for error count threshold `tests/alerts/error_count_threshold.spec.ts` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../src/lib/timerange.ts | 18 +- .../kbn-apm-synthtrace-client/tsconfig.json | 3 + .../common/rules/default_action_message.ts | 60 +++++++ x-pack/plugins/apm/common/rules/schema.ts | 71 ++++++++ .../rule_types/register_apm_rule_types.ts | 58 ++---- .../anomaly/register_anomaly_rule_type.ts | 21 +-- .../register_error_count_rule_type.test.ts | 6 +- .../register_error_count_rule_type.ts | 48 +++-- ...ter_transaction_duration_rule_type.test.ts | 2 +- ...register_transaction_duration_rule_type.ts | 74 ++++---- ...r_transaction_error_rate_rule_type.test.ts | 2 +- ...gister_transaction_error_rate_rule_type.ts | 56 +++--- .../tests/alerts/alerting_api_helper.ts | 117 +++++++++++++ .../tests/alerts/anomaly_alert.spec.ts | 52 +++--- .../alerts/error_count_threshold.spec.ts | 165 ++++++++++++++++++ .../tests/alerts/wait_for_rule_status.ts | 73 ++++---- .../service_group_count.spec.ts | 42 ++--- .../tests/services/service_alerts.spec.ts | 42 ++--- 18 files changed, 624 insertions(+), 286 deletions(-) create mode 100644 x-pack/plugins/apm/common/rules/default_action_message.ts create mode 100644 x-pack/plugins/apm/common/rules/schema.ts create mode 100644 x-pack/test/apm_api_integration/tests/alerts/alerting_api_helper.ts create mode 100644 x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts diff --git a/packages/kbn-apm-synthtrace-client/src/lib/timerange.ts b/packages/kbn-apm-synthtrace-client/src/lib/timerange.ts index 2dd0659f9cc19..0817ea3d0e34f 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/timerange.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/timerange.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - +import datemath from '@kbn/datemath'; import type { Moment } from 'moment'; import { Interval } from './interval'; @@ -23,12 +23,22 @@ export class Timerange { type DateLike = Date | number | Moment | string; -function getDateFrom(date: DateLike): Date { +function getDateFrom(date: DateLike, now: Date): Date { if (date instanceof Date) return date; + + if (typeof date === 'string') { + const parsed = datemath.parse(date, { forceNow: now }); + if (parsed && parsed.isValid()) { + return parsed.toDate(); + } + } + if (typeof date === 'number' || typeof date === 'string') return new Date(date); + return date.toDate(); } -export function timerange(from: Date | number | Moment, to: Date | number | Moment) { - return new Timerange(getDateFrom(from), getDateFrom(to)); +export function timerange(from: DateLike, to: DateLike) { + const now = new Date(); + return new Timerange(getDateFrom(from, now), getDateFrom(to, now)); } diff --git a/packages/kbn-apm-synthtrace-client/tsconfig.json b/packages/kbn-apm-synthtrace-client/tsconfig.json index 8d1c9cae899a3..8286fda7455b0 100644 --- a/packages/kbn-apm-synthtrace-client/tsconfig.json +++ b/packages/kbn-apm-synthtrace-client/tsconfig.json @@ -11,5 +11,8 @@ "include": ["**/*.ts"], "exclude": [ "target/**/*", + ], + "kbn_references": [ + "@kbn/datemath", ] } diff --git a/x-pack/plugins/apm/common/rules/default_action_message.ts b/x-pack/plugins/apm/common/rules/default_action_message.ts new file mode 100644 index 0000000000000..503bc1ca3cd26 --- /dev/null +++ b/x-pack/plugins/apm/common/rules/default_action_message.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 { i18n } from '@kbn/i18n'; + +export const errorCountMessage = i18n.translate( + 'xpack.apm.alertTypes.errorCount.defaultActionMessage', + { + defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: + +- Service name: \\{\\{context.serviceName\\}\\} +- Environment: \\{\\{context.environment\\}\\} +- Threshold: \\{\\{context.threshold\\}\\} +- Triggered value: \\{\\{context.triggerValue\\}\\} errors over the last \\{\\{context.interval\\}\\}`, + } +); + +export const transactionDurationMessage = i18n.translate( + 'xpack.apm.alertTypes.transactionDuration.defaultActionMessage', + { + defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: + +- Service name: \\{\\{context.serviceName\\}\\} +- Type: \\{\\{context.transactionType\\}\\} +- Environment: \\{\\{context.environment\\}\\} +- Latency threshold: \\{\\{context.threshold\\}\\}ms +- Latency observed: \\{\\{context.triggerValue\\}\\} over the last \\{\\{context.interval\\}\\}`, + } +); + +export const transactionErrorRateMessage = i18n.translate( + 'xpack.apm.alertTypes.transactionErrorRate.defaultActionMessage', + { + defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: + +- Service name: \\{\\{context.serviceName\\}\\} +- Type: \\{\\{context.transactionType\\}\\} +- Environment: \\{\\{context.environment\\}\\} +- Threshold: \\{\\{context.threshold\\}\\}% +- Triggered value: \\{\\{context.triggerValue\\}\\}% of errors over the last \\{\\{context.interval\\}\\}`, + } +); + +export const anomalyMessage = i18n.translate( + 'xpack.apm.alertTypes.transactionDurationAnomaly.defaultActionMessage', + { + defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: + +- Service name: \\{\\{context.serviceName\\}\\} +- Type: \\{\\{context.transactionType\\}\\} +- Environment: \\{\\{context.environment\\}\\} +- Severity threshold: \\{\\{context.threshold\\}\\} +- Severity value: \\{\\{context.triggerValue\\}\\} +`, + } +); diff --git a/x-pack/plugins/apm/common/rules/schema.ts b/x-pack/plugins/apm/common/rules/schema.ts new file mode 100644 index 0000000000000..58a5b40da41f2 --- /dev/null +++ b/x-pack/plugins/apm/common/rules/schema.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 { schema, TypeOf } from '@kbn/config-schema'; +import { ANOMALY_SEVERITY } from '../ml_constants'; +import { AggregationType, ApmRuleType } from './apm_rule_types'; + +export const errorCountParamsSchema = schema.object({ + windowSize: schema.number(), + windowUnit: schema.string(), + threshold: schema.number(), + serviceName: schema.maybe(schema.string()), + environment: schema.string(), +}); + +export const transactionDurationParamsSchema = schema.object({ + serviceName: schema.maybe(schema.string()), + transactionType: schema.maybe(schema.string()), + windowSize: schema.number(), + windowUnit: schema.string(), + threshold: schema.number(), + aggregationType: schema.oneOf([ + schema.literal(AggregationType.Avg), + schema.literal(AggregationType.P95), + schema.literal(AggregationType.P99), + ]), + environment: schema.string(), +}); + +export const anomalyParamsSchema = schema.object({ + serviceName: schema.maybe(schema.string()), + transactionType: schema.maybe(schema.string()), + windowSize: schema.number(), + windowUnit: schema.string(), + environment: schema.string(), + anomalySeverityType: schema.oneOf([ + schema.literal(ANOMALY_SEVERITY.CRITICAL), + schema.literal(ANOMALY_SEVERITY.MAJOR), + schema.literal(ANOMALY_SEVERITY.MINOR), + schema.literal(ANOMALY_SEVERITY.WARNING), + ]), +}); + +export const transactionErrorRateParamsSchema = schema.object({ + windowSize: schema.number(), + windowUnit: schema.string(), + threshold: schema.number(), + transactionType: schema.maybe(schema.string()), + serviceName: schema.maybe(schema.string()), + environment: schema.string(), +}); + +type ErrorCountParamsType = TypeOf; +type TransactionDurationParamsType = TypeOf< + typeof transactionDurationParamsSchema +>; +type AnomalyParamsType = TypeOf; +type TransactionErrorRateParamsType = TypeOf< + typeof transactionErrorRateParamsSchema +>; + +export interface ApmRuleParamsType { + [ApmRuleType.TransactionDuration]: TransactionDurationParamsType; + [ApmRuleType.ErrorCount]: ErrorCountParamsType; + [ApmRuleType.Anomaly]: AnomalyParamsType; + [ApmRuleType.TransactionErrorRate]: TransactionErrorRateParamsType; +} diff --git a/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts b/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts index ed9971307bf64..f355ea4c2f6eb 100644 --- a/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts +++ b/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts @@ -14,6 +14,12 @@ import { getAlertUrlTransaction, } from '../../../../common/utils/formatters'; import { ApmRuleType } from '../../../../common/rules/apm_rule_types'; +import { + anomalyMessage, + errorCountMessage, + transactionDurationMessage, + transactionErrorRateMessage, +} from '../../../../common/rules/default_action_message'; // copied from elasticsearch_fieldnames.ts to limit page load bundle size const SERVICE_ENVIRONMENT = 'service.environment'; @@ -54,17 +60,7 @@ export function registerApmRuleTypes( ) ), requiresAppContext: false, - defaultActionMessage: i18n.translate( - 'xpack.apm.alertTypes.errorCount.defaultActionMessage', - { - defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: - -- Service name: \\{\\{context.serviceName\\}\\} -- Environment: \\{\\{context.environment\\}\\} -- Threshold: \\{\\{context.threshold\\}\\} errors -- Triggered value: \\{\\{context.triggerValue\\}\\} errors over the last \\{\\{context.interval\\}\\}`, - } - ), + defaultActionMessage: errorCountMessage, }); observabilityRuleTypeRegistry.register({ @@ -104,18 +100,7 @@ export function registerApmRuleTypes( ) ), requiresAppContext: false, - defaultActionMessage: i18n.translate( - 'xpack.apm.alertTypes.transactionDuration.defaultActionMessage', - { - defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: - -- Service name: \\{\\{context.serviceName\\}\\} -- Type: \\{\\{context.transactionType\\}\\} -- Environment: \\{\\{context.environment\\}\\} -- Latency threshold: \\{\\{context.threshold\\}\\}ms -- Latency observed: \\{\\{context.triggerValue\\}\\} over the last \\{\\{context.interval\\}\\}`, - } - ), + defaultActionMessage: transactionDurationMessage, }); observabilityRuleTypeRegistry.register({ @@ -153,18 +138,7 @@ export function registerApmRuleTypes( ) ), requiresAppContext: false, - defaultActionMessage: i18n.translate( - 'xpack.apm.alertTypes.transactionErrorRate.defaultActionMessage', - { - defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: - -- Service name: \\{\\{context.serviceName\\}\\} -- Type: \\{\\{context.transactionType\\}\\} -- Environment: \\{\\{context.environment\\}\\} -- Threshold: \\{\\{context.threshold\\}\\}% -- Triggered value: \\{\\{context.triggerValue\\}\\}% of errors over the last \\{\\{context.interval\\}\\}`, - } - ), + defaultActionMessage: transactionErrorRateMessage, }); observabilityRuleTypeRegistry.register({ @@ -199,18 +173,6 @@ export function registerApmRuleTypes( ) ), requiresAppContext: false, - defaultActionMessage: i18n.translate( - 'xpack.apm.alertTypes.transactionDurationAnomaly.defaultActionMessage', - { - defaultMessage: `\\{\\{alertName\\}\\} alert is firing because of the following conditions: - -- Service name: \\{\\{context.serviceName\\}\\} -- Type: \\{\\{context.transactionType\\}\\} -- Environment: \\{\\{context.environment\\}\\} -- Severity threshold: \\{\\{context.threshold\\}\\} -- Severity value: \\{\\{context.triggerValue\\}\\} -`, - } - ), + defaultActionMessage: anomalyMessage, }); } diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts index 529efb583b7dd..a10d803ef6d86 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts @@ -5,7 +5,6 @@ * 2.0. */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { schema } from '@kbn/config-schema'; import { KibanaRequest } from '@kbn/core/server'; import datemath from '@kbn/datemath'; import type { ESSearchResponse } from '@kbn/es-types'; @@ -36,7 +35,6 @@ import { getEnvironmentEsField, getEnvironmentLabel, } from '../../../../../common/environment_filter_values'; -import { ANOMALY_SEVERITY } from '../../../../../common/ml_constants'; import { ANOMALY_ALERT_SEVERITY_TYPES, ApmRuleType, @@ -49,20 +47,7 @@ import { getMLJobs } from '../../../service_map/get_service_anomalies'; import { apmActionVariables } from '../../action_variables'; import { RegisterRuleDependencies } from '../../register_apm_rule_types'; import { getServiceGroupFieldsForAnomaly } from './get_service_group_fields_for_anomaly'; - -const paramsSchema = schema.object({ - serviceName: schema.maybe(schema.string()), - transactionType: schema.maybe(schema.string()), - windowSize: schema.number(), - windowUnit: schema.string(), - environment: schema.string(), - anomalySeverityType: schema.oneOf([ - schema.literal(ANOMALY_SEVERITY.CRITICAL), - schema.literal(ANOMALY_SEVERITY.MAJOR), - schema.literal(ANOMALY_SEVERITY.MINOR), - schema.literal(ANOMALY_SEVERITY.WARNING), - ]), -}); +import { anomalyParamsSchema } from '../../../../../common/rules/schema'; const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.Anomaly]; @@ -86,9 +71,7 @@ export function registerAnomalyRuleType({ name: ruleTypeConfig.name, actionGroups: ruleTypeConfig.actionGroups, defaultActionGroupId: ruleTypeConfig.defaultActionGroupId, - validate: { - params: paramsSchema, - }, + validate: { params: anomalyParamsSchema }, actionVariables: { context: [ ...(observability.getAlertDetailsConfig()?.apm.enabled diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts index 705804cfa74f4..6d6752eba0ce5 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.test.ts @@ -146,7 +146,7 @@ describe('Error count alert', () => { threshold: 2, triggerValue: 5, reason: 'Error count is 5 in the last 5 mins for foo. Alert when > 2.', - interval: '5m', + interval: '5 mins', viewInAppUrl: 'http://localhost:5601/eyr/app/apm/services/foo/errors?environment=env-foo', }); @@ -159,7 +159,7 @@ describe('Error count alert', () => { threshold: 2, triggerValue: 4, reason: 'Error count is 4 in the last 5 mins for foo. Alert when > 2.', - interval: '5m', + interval: '5 mins', viewInAppUrl: 'http://localhost:5601/eyr/app/apm/services/foo/errors?environment=env-foo-2', }); @@ -172,7 +172,7 @@ describe('Error count alert', () => { reason: 'Error count is 3 in the last 5 mins for bar. Alert when > 2.', threshold: 2, triggerValue: 3, - interval: '5m', + interval: '5 mins', viewInAppUrl: 'http://localhost:5601/eyr/app/apm/services/bar/errors?environment=env-bar', }); diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts index 54bfb00d468b0..c811e71fe1f17 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/error_count/register_error_count_rule_type.ts @@ -5,54 +5,49 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; -import { firstValueFrom } from 'rxjs'; +import { getAlertDetailsUrl } from '@kbn/infra-plugin/server/lib/alerting/common/utils'; +import { + formatDurationFromTimeUnitChar, + ProcessorEvent, + TimeUnitChar, +} from '@kbn/observability-plugin/common'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, ALERT_REASON, } from '@kbn/rule-data-utils'; import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server'; -import { termQuery } from '@kbn/observability-plugin/server'; -import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { getAlertDetailsUrl } from '@kbn/infra-plugin/server/lib/alerting/common/utils'; import { addSpaceIdToPath } from '@kbn/spaces-plugin/common'; - +import { firstValueFrom } from 'rxjs'; import { ENVIRONMENT_NOT_DEFINED, getEnvironmentEsField, getEnvironmentLabel, } from '../../../../../common/environment_filter_values'; -import { getAlertUrlErrorCount } from '../../../../../common/utils/formatters'; -import { - ApmRuleType, - APM_SERVER_FEATURE_ID, - RULE_TYPES_CONFIG, - formatErrorCountReason, -} from '../../../../../common/rules/apm_rule_types'; import { PROCESSOR_EVENT, SERVICE_ENVIRONMENT, SERVICE_NAME, } from '../../../../../common/es_fields/apm'; +import { + ApmRuleType, + APM_SERVER_FEATURE_ID, + formatErrorCountReason, + RULE_TYPES_CONFIG, +} from '../../../../../common/rules/apm_rule_types'; +import { errorCountParamsSchema } from '../../../../../common/rules/schema'; import { environmentQuery } from '../../../../../common/utils/environment_query'; +import { getAlertUrlErrorCount } from '../../../../../common/utils/formatters'; import { getApmIndices } from '../../../settings/apm_indices/get_apm_indices'; import { apmActionVariables } from '../../action_variables'; import { alertingEsClient } from '../../alerting_es_client'; import { RegisterRuleDependencies } from '../../register_apm_rule_types'; import { - getServiceGroupFieldsAgg, getServiceGroupFields, + getServiceGroupFieldsAgg, } from '../get_service_group_fields'; -const paramsSchema = schema.object({ - windowSize: schema.number(), - windowUnit: schema.string(), - threshold: schema.number(), - serviceName: schema.maybe(schema.string()), - environment: schema.string(), -}); - const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.ErrorCount]; export function registerErrorCountRuleType({ @@ -74,9 +69,7 @@ export function registerErrorCountRuleType({ name: ruleTypeConfig.name, actionGroups: ruleTypeConfig.actionGroups, defaultActionGroupId: ruleTypeConfig.defaultActionGroupId, - validate: { - params: paramsSchema, - }, + validate: { params: errorCountParamsSchema }, actionVariables: { context: [ ...(observability.getAlertDetailsConfig()?.apm.enabled @@ -214,7 +207,10 @@ export function registerErrorCountRuleType({ .scheduleActions(ruleTypeConfig.defaultActionGroupId, { alertDetailsUrl, environment: getEnvironmentLabel(environment), - interval: `${ruleParams.windowSize}${ruleParams.windowUnit}`, + interval: formatDurationFromTimeUnitChar( + ruleParams.windowSize, + ruleParams.windowUnit as TimeUnitChar + ), reason: alertReason, serviceName, threshold: ruleParams.threshold, diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts index cebf71f1bad97..dcd8994860ae7 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.test.ts @@ -60,7 +60,7 @@ describe('registerTransactionDurationRuleType', () => { 'http://localhost:5601/eyr/app/observability/alerts/' ), environment: 'Not defined', - interval: `5m`, + interval: `5 mins`, reason: 'Avg. latency is 5,500 ms in the last 5 mins for opbeans-java. Alert when > 3,000 ms.', transactionType: 'request', diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts index 803945568494b..bc11cee03a506 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type.ts @@ -6,41 +6,46 @@ */ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { schema } from '@kbn/config-schema'; +import { getAlertDetailsUrl } from '@kbn/infra-plugin/server/lib/alerting/common/utils'; +import { + formatDurationFromTimeUnitChar, + ProcessorEvent, + TimeUnitChar, +} from '@kbn/observability-plugin/common'; +import { asDuration } from '@kbn/observability-plugin/common/utils/formatters'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, ALERT_REASON, } from '@kbn/rule-data-utils'; -import { firstValueFrom } from 'rxjs'; -import { asDuration } from '@kbn/observability-plugin/common/utils/formatters'; -import { termQuery } from '@kbn/observability-plugin/server'; import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server'; -import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { getAlertDetailsUrl } from '@kbn/infra-plugin/server/lib/alerting/common/utils'; import { addSpaceIdToPath } from '@kbn/spaces-plugin/common'; -import { getAlertUrlTransaction } from '../../../../../common/utils/formatters'; +import { firstValueFrom } from 'rxjs'; import { SearchAggregatedTransactionSetting } from '../../../../../common/aggregated_transactions'; import { - ApmRuleType, - AggregationType, - RULE_TYPES_CONFIG, - APM_SERVER_FEATURE_ID, - formatTransactionDurationReason, -} from '../../../../../common/rules/apm_rule_types'; + ENVIRONMENT_NOT_DEFINED, + getEnvironmentEsField, + getEnvironmentLabel, +} from '../../../../../common/environment_filter_values'; import { PROCESSOR_EVENT, + SERVICE_ENVIRONMENT, SERVICE_NAME, TRANSACTION_TYPE, - SERVICE_ENVIRONMENT, } from '../../../../../common/es_fields/apm'; import { - ENVIRONMENT_NOT_DEFINED, - getEnvironmentEsField, - getEnvironmentLabel, -} from '../../../../../common/environment_filter_values'; + ApmRuleType, + APM_SERVER_FEATURE_ID, + formatTransactionDurationReason, + RULE_TYPES_CONFIG, +} from '../../../../../common/rules/apm_rule_types'; +import { transactionDurationParamsSchema } from '../../../../../common/rules/schema'; import { environmentQuery } from '../../../../../common/utils/environment_query'; -import { getDurationFormatter } from '../../../../../common/utils/formatters'; +import { + getAlertUrlTransaction, + getDurationFormatter, +} from '../../../../../common/utils/formatters'; import { getDocumentTypeFilterForTransactions, getDurationFieldForTransactions, @@ -49,28 +54,14 @@ import { getApmIndices } from '../../../settings/apm_indices/get_apm_indices'; import { apmActionVariables } from '../../action_variables'; import { alertingEsClient } from '../../alerting_es_client'; import { RegisterRuleDependencies } from '../../register_apm_rule_types'; -import { - averageOrPercentileAgg, - getMultiTermsSortOrder, -} from './average_or_percentile_agg'; import { getServiceGroupFields, getServiceGroupFieldsAgg, } from '../get_service_group_fields'; - -const paramsSchema = schema.object({ - serviceName: schema.maybe(schema.string()), - transactionType: schema.maybe(schema.string()), - windowSize: schema.number(), - windowUnit: schema.string(), - threshold: schema.number(), - aggregationType: schema.oneOf([ - schema.literal(AggregationType.Avg), - schema.literal(AggregationType.P95), - schema.literal(AggregationType.P99), - ]), - environment: schema.string(), -}); +import { + averageOrPercentileAgg, + getMultiTermsSortOrder, +} from './average_or_percentile_agg'; const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.TransactionDuration]; @@ -92,9 +83,7 @@ export function registerTransactionDurationRuleType({ name: ruleTypeConfig.name, actionGroups: ruleTypeConfig.actionGroups, defaultActionGroupId: ruleTypeConfig.defaultActionGroupId, - validate: { - params: paramsSchema, - }, + validate: { params: transactionDurationParamsSchema }, actionVariables: { context: [ ...(observability.getAlertDetailsConfig()?.apm.enabled @@ -289,7 +278,10 @@ export function registerTransactionDurationRuleType({ .scheduleActions(ruleTypeConfig.defaultActionGroupId, { alertDetailsUrl, environment: environmentLabel, - interval: `${ruleParams.windowSize}${ruleParams.windowUnit}`, + interval: formatDurationFromTimeUnitChar( + ruleParams.windowSize, + ruleParams.windowUnit as TimeUnitChar + ), reason, serviceName, threshold: ruleParams.threshold, diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts index 38de7d48cce4c..02eb14e782df3 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.test.ts @@ -131,7 +131,7 @@ describe('Transaction error rate alert', () => { 'Failed transactions is 10% in the last 5 mins for foo. Alert when > 10%.', threshold: 10, triggerValue: '10', - interval: '5m', + interval: '5 mins', viewInAppUrl: 'http://localhost:5601/eyr/app/apm/services/foo?transactionType=type-foo&environment=env-foo', }); diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts index 308ed32e3b5a1..df94a3e8a3c75 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type.ts @@ -5,31 +5,28 @@ * 2.0. */ -import { schema } from '@kbn/config-schema'; -import { firstValueFrom } from 'rxjs'; +import { getAlertDetailsUrl } from '@kbn/infra-plugin/server/lib/alerting/common/utils'; +import { + formatDurationFromTimeUnitChar, + ProcessorEvent, + TimeUnitChar, +} from '@kbn/observability-plugin/common'; +import { asPercent } from '@kbn/observability-plugin/common/utils/formatters'; +import { termQuery } from '@kbn/observability-plugin/server'; import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, ALERT_REASON, } from '@kbn/rule-data-utils'; import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server'; -import { asPercent } from '@kbn/observability-plugin/common/utils/formatters'; -import { termQuery } from '@kbn/observability-plugin/server'; import { addSpaceIdToPath } from '@kbn/spaces-plugin/common'; -import { ProcessorEvent } from '@kbn/observability-plugin/common'; -import { getAlertDetailsUrl } from '@kbn/infra-plugin/server/lib/alerting/common/utils'; +import { firstValueFrom } from 'rxjs'; +import { SearchAggregatedTransactionSetting } from '../../../../../common/aggregated_transactions'; import { ENVIRONMENT_NOT_DEFINED, getEnvironmentEsField, getEnvironmentLabel, } from '../../../../../common/environment_filter_values'; -import { getAlertUrlTransaction } from '../../../../../common/utils/formatters'; -import { - ApmRuleType, - RULE_TYPES_CONFIG, - APM_SERVER_FEATURE_ID, - formatTransactionErrorRateReason, -} from '../../../../../common/rules/apm_rule_types'; import { EVENT_OUTCOME, PROCESSOR_EVENT, @@ -38,28 +35,28 @@ import { TRANSACTION_TYPE, } from '../../../../../common/es_fields/apm'; import { EventOutcome } from '../../../../../common/event_outcome'; -import { asDecimalOrInteger } from '../../../../../common/utils/formatters'; +import { + ApmRuleType, + APM_SERVER_FEATURE_ID, + formatTransactionErrorRateReason, + RULE_TYPES_CONFIG, +} from '../../../../../common/rules/apm_rule_types'; +import { transactionErrorRateParamsSchema } from '../../../../../common/rules/schema'; import { environmentQuery } from '../../../../../common/utils/environment_query'; +import { + asDecimalOrInteger, + getAlertUrlTransaction, +} from '../../../../../common/utils/formatters'; +import { getDocumentTypeFilterForTransactions } from '../../../../lib/helpers/transactions'; import { getApmIndices } from '../../../settings/apm_indices/get_apm_indices'; import { apmActionVariables } from '../../action_variables'; import { alertingEsClient } from '../../alerting_es_client'; import { RegisterRuleDependencies } from '../../register_apm_rule_types'; -import { SearchAggregatedTransactionSetting } from '../../../../../common/aggregated_transactions'; -import { getDocumentTypeFilterForTransactions } from '../../../../lib/helpers/transactions'; import { getServiceGroupFields, getServiceGroupFieldsAgg, } from '../get_service_group_fields'; -const paramsSchema = schema.object({ - windowSize: schema.number(), - windowUnit: schema.string(), - threshold: schema.number(), - transactionType: schema.maybe(schema.string()), - serviceName: schema.maybe(schema.string()), - environment: schema.string(), -}); - const ruleTypeConfig = RULE_TYPES_CONFIG[ApmRuleType.TransactionErrorRate]; export function registerTransactionErrorRateRuleType({ @@ -81,9 +78,7 @@ export function registerTransactionErrorRateRuleType({ name: ruleTypeConfig.name, actionGroups: ruleTypeConfig.actionGroups, defaultActionGroupId: ruleTypeConfig.defaultActionGroupId, - validate: { - params: paramsSchema, - }, + validate: { params: transactionErrorRateParamsSchema }, actionVariables: { context: [ ...(observability.getAlertDetailsConfig()?.apm.enabled @@ -285,7 +280,10 @@ export function registerTransactionErrorRateRuleType({ .scheduleActions(ruleTypeConfig.defaultActionGroupId, { alertDetailsUrl, environment: getEnvironmentLabel(environment), - interval: `${ruleParams.windowSize}${ruleParams.windowUnit}`, + interval: formatDurationFromTimeUnitChar( + ruleParams.windowSize, + ruleParams.windowUnit as TimeUnitChar + ), reason: reasonMessage, serviceName, threshold: ruleParams.threshold, diff --git a/x-pack/test/apm_api_integration/tests/alerts/alerting_api_helper.ts b/x-pack/test/apm_api_integration/tests/alerts/alerting_api_helper.ts new file mode 100644 index 0000000000000..b6c5b891b8353 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/alerts/alerting_api_helper.ts @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SuperTest, Test } from 'supertest'; +import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleParamsType } from '@kbn/apm-plugin/common/rules/schema'; +import { ApmDocumentType } from '@kbn/apm-plugin/common/document_type'; +import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; +import { ApmApiClient } from '../../common/config'; + +export async function createIndexConnector({ + supertest, + name, + indexName, +}: { + supertest: SuperTest; + name: string; + indexName: string; +}) { + const { body } = await supertest + .post(`/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name, + config: { + index: indexName, + refresh: true, + }, + connector_type_id: '.index', + }); + return body.id as string; +} + +export async function createApmRule({ + supertest, + name, + ruleTypeId, + params, + actions = [], +}: { + supertest: SuperTest; + ruleTypeId: T; + name: string; + params: ApmRuleParamsType[T]; + actions?: any[]; +}) { + const { body } = await supertest + .post(`/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send({ + params, + consumer: 'apm', + schedule: { + interval: '1m', + }, + tags: ['apm'], + name, + rule_type_id: ruleTypeId, + actions, + }); + return body; +} + +function getTimerange() { + return { + start: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), + end: new Date(Date.now() + 5 * 60 * 1000).toISOString(), + }; +} + +export async function fetchServiceInventoryAlertCounts(apmApiClient: ApmApiClient) { + const timerange = getTimerange(); + const serviceInventoryResponse = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services', + params: { + query: { + ...timerange, + environment: 'ENVIRONMENT_ALL', + kuery: '', + probability: 1, + documentType: ApmDocumentType.ServiceTransactionMetric, + rollupInterval: RollupInterval.SixtyMinutes, + }, + }, + }); + return serviceInventoryResponse.body.items.reduce>((acc, item) => { + return { ...acc, [item.serviceName]: item.alertsCount ?? 0 }; + }, {}); +} + +export async function fetchServiceTabAlertCount({ + apmApiClient, + serviceName, +}: { + apmApiClient: ApmApiClient; + serviceName: string; +}) { + const timerange = getTimerange(); + const alertsCountReponse = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/alerts_count', + params: { + path: { + serviceName, + }, + query: { + ...timerange, + environment: 'ENVIRONMENT_ALL', + }, + }, + }); + + return alertsCountReponse.body.alertsCount; +} 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 39c81e71948a0..a72760ca339ce 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 @@ -9,8 +9,10 @@ import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import expect from '@kbn/expect'; import { range } from 'lodash'; +import { ANOMALY_SEVERITY } from '@kbn/apm-plugin/common/ml_constants'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { createAndRunApmMlJobs } from '../../common/utils/create_and_run_apm_ml_jobs'; +import { createApmRule } from './alerting_api_helper'; import { waitForRuleStatus } from './wait_for_rule_status'; export default function ApiTest({ getService }: FtrProviderContext) { @@ -18,7 +20,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const ml = getService('ml'); - const log = getService('log'); const es = getService('es'); const synthtraceEsClient = getService('synthtraceEsClient'); @@ -81,36 +82,29 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); it('checks if alert is active', async () => { - const { body: createdRule } = await supertest - .post(`/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send({ - params: { - environment: 'production', - windowSize: 99, - windowUnit: 'y', - anomalySeverityType: 'warning', - }, - consumer: 'apm', - schedule: { - interval: '1m', - }, - tags: ['apm', 'service.name:service-a'], - name: 'Latency anomaly | service-a', - rule_type_id: ApmRuleType.Anomaly, - notify_when: 'onActiveAlert', - actions: [], - }); - - ruleId = createdRule.id; - - const executionStatus = await waitForRuleStatus({ - id: ruleId, - expectedStatus: 'active', + const createdRule = await createApmRule({ supertest, - log, + name: 'Latency anomaly | service-a', + params: { + environment: 'production', + windowSize: 99, + windowUnit: 'y', + anomalySeverityType: ANOMALY_SEVERITY.WARNING, + }, + ruleTypeId: ApmRuleType.Anomaly, }); - expect(executionStatus.status).to.be('active'); + + ruleId = createdRule.id; + if (!ruleId) { + expect(ruleId).to.not.eql(undefined); + } else { + const executionStatus = await waitForRuleStatus({ + id: ruleId, + expectedStatus: 'active', + supertest, + }); + expect(executionStatus.status).to.be('active'); + } }); }); } diff --git a/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts new file mode 100644 index 0000000000000..a19f1ef93503a --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts @@ -0,0 +1,165 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { errorCountMessage } from '@kbn/apm-plugin/common/rules/default_action_message'; +import { apm, timerange } from '@kbn/apm-synthtrace-client'; +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { + createApmRule, + createIndexConnector, + fetchServiceInventoryAlertCounts, + fetchServiceTabAlertCount, +} from './alerting_api_helper'; +import { waitForRuleStatus, waitForDocumentInIndex } from './wait_for_rule_status'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const registry = getService('registry'); + + const supertest = getService('supertest'); + const es = getService('es'); + const apmApiClient = getService('apmApiClient'); + const esDeleteAllIndices = getService('esDeleteAllIndices'); + + const synthtraceEsClient = getService('synthtraceEsClient'); + + registry.when('error count threshold alert', { config: 'basic', archives: [] }, () => { + let ruleId: string; + let actionId: string | undefined; + + const INDEX_NAME = 'error-count'; + + before(async () => { + const opbeansJava = apm + .service({ name: 'opbeans-java', environment: 'production', agentName: 'java' }) + .instance('instance'); + const opbeansNode = apm + .service({ name: 'opbeans-node', environment: 'production', agentName: 'node' }) + .instance('instance'); + const events = timerange('now-15m', 'now') + .ratePerMinute(1) + .generator((timestamp) => { + return [ + opbeansJava + .transaction({ transactionName: 'tx-java' }) + .timestamp(timestamp) + .duration(100) + .failure() + .errors( + opbeansJava + .error({ message: '[ResponseError] index_not_found_exception' }) + .timestamp(timestamp + 50) + ), + opbeansNode + .transaction({ transactionName: 'tx-node' }) + .timestamp(timestamp) + .duration(100) + .success(), + ]; + }); + await synthtraceEsClient.index(events); + }); + + after(async () => { + await synthtraceEsClient.clean(); + await supertest.delete(`/api/alerting/rule/${ruleId}`).set('kbn-xsrf', 'foo'); + await supertest.delete(`/api/actions/connector/${actionId}`).set('kbn-xsrf', 'foo'); + await esDeleteAllIndices(['.alerts*', INDEX_NAME]); + await es.deleteByQuery({ + index: '.kibana-event-log-*', + query: { term: { 'kibana.alert.rule.consumer': 'apm' } }, + }); + }); + + describe('create alert', () => { + before(async () => { + actionId = await createIndexConnector({ + supertest, + name: 'Error count API test', + indexName: INDEX_NAME, + }); + const createdRule = await createApmRule({ + supertest, + ruleTypeId: ApmRuleType.ErrorCount, + name: 'Apm error count', + params: { + environment: 'production', + threshold: 1, + windowSize: 1, + windowUnit: 'h', + }, + actions: [ + { + group: 'threshold_met', + id: actionId, + params: { + documents: [{ message: errorCountMessage }], + }, + frequency: { + notify_when: 'onActionGroupChange', + throttle: null, + summary: false, + }, + }, + ], + }); + expect(createdRule.id).to.not.eql(undefined); + ruleId = createdRule.id; + }); + + it('checks if alert is active', async () => { + const executionStatus = await waitForRuleStatus({ + id: ruleId, + expectedStatus: 'active', + supertest, + }); + expect(executionStatus.status).to.be('active'); + }); + + it('returns correct message', async () => { + const resp = await waitForDocumentInIndex<{ message: string }>({ + es, + indexName: INDEX_NAME, + }); + + expect(resp.hits.hits[0]._source?.message).eql( + `Apm error count alert is firing because of the following conditions: + +- Service name: opbeans-java +- Environment: production +- Threshold: 1 +- Triggered value: 15 errors over the last 1 hr` + ); + }); + + it('shows the correct alert count for each service on service inventory', async () => { + const serviceInventoryAlertCounts = await fetchServiceInventoryAlertCounts(apmApiClient); + expect(serviceInventoryAlertCounts).to.eql({ + 'opbeans-node': 0, + 'opbeans-java': 1, + }); + }); + + it('shows the correct alert count in opbeans-java service', async () => { + const serviceTabAlertCount = await fetchServiceTabAlertCount({ + apmApiClient, + serviceName: 'opbeans-java', + }); + expect(serviceTabAlertCount).to.be(1); + }); + + it('shows the correct alert count in opbeans-node service', async () => { + const serviceTabAlertCount = await fetchServiceTabAlertCount({ + apmApiClient, + serviceName: 'opbeans-node', + }); + expect(serviceTabAlertCount).to.be(0); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/alerts/wait_for_rule_status.ts b/x-pack/test/apm_api_integration/tests/alerts/wait_for_rule_status.ts index f4814358f1636..44da2bea36bf2 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/wait_for_rule_status.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/wait_for_rule_status.ts @@ -4,53 +4,52 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { ToolingLog } from '@kbn/tooling-log'; -import expect from '@kbn/expect'; +import type { Client } from '@elastic/elasticsearch'; +import type { + AggregationsAggregate, + SearchResponse, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import pRetry from 'p-retry'; import type SuperTest from 'supertest'; -const WAIT_FOR_STATUS_INCREMENT = 500; - export async function waitForRuleStatus({ id, expectedStatus, - waitMillis = 10000, supertest, - log, }: { + id: string; expectedStatus: string; supertest: SuperTest.SuperTest; - log: ToolingLog; - waitMillis?: number; - id?: string; }): Promise> { - if (waitMillis < 0 || !id) { - expect().fail(`waiting for alert ${id} status ${expectedStatus} timed out`); - } - - const response = await supertest.get(`/api/alerting/rule/${id}`); - expect(response.status).to.eql(200); - - const { execution_status: executionStatus } = response.body || {}; - const { status } = executionStatus || {}; - - const message = `waitForStatus(${expectedStatus}): got ${JSON.stringify(executionStatus)}`; - - if (status === expectedStatus) { - return executionStatus; - } - - log.debug(`${message}, retrying`); - - await delay(WAIT_FOR_STATUS_INCREMENT); - return await waitForRuleStatus({ - id, - expectedStatus, - waitMillis: waitMillis - WAIT_FOR_STATUS_INCREMENT, - supertest, - log, - }); + return pRetry( + async () => { + const response = await supertest.get(`/api/alerting/rule/${id}`); + const { execution_status: executionStatus } = response.body || {}; + const { status } = executionStatus || {}; + if (status !== expectedStatus) { + throw new Error(`waitForStatus(${expectedStatus}): got ${status}`); + } + return executionStatus; + }, + { retries: 10 } + ); } -async function delay(millis: number): Promise { - await new Promise((resolve) => setTimeout(resolve, millis)); +export async function waitForDocumentInIndex({ + es, + indexName, +}: { + es: Client; + indexName: string; +}): Promise>> { + return pRetry( + async () => { + const response = await es.search({ index: indexName }); + if (response.hits.hits.length === 0) { + throw new Error('No hits found'); + } + return response; + }, + { retries: 10 } + ); } diff --git a/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts b/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts index 69e3d7678ca9e..abae62f2012a6 100644 --- a/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts +++ b/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts @@ -4,10 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { AggregationType, ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { waitForActiveAlert } from '../../../common/utils/wait_for_active_alert'; +import { createApmRule } from '../../alerts/alerting_api_helper'; import { createServiceGroupApi, deleteAllServiceGroups, @@ -26,28 +27,21 @@ export default function ApiTest({ getService }: FtrProviderContext) { const start = Date.now() - 24 * 60 * 60 * 1000; const end = Date.now(); - async function createRule() { - return supertest - .post(`/api/alerting/rule`) - .set('kbn-xsrf', 'true') - .send({ - params: { - serviceName: 'synth-go', - transactionType: '', - windowSize: 99, - windowUnit: 'y', - threshold: 100, - aggregationType: 'avg', - environment: 'testing', - }, - consumer: 'apm', - schedule: { interval: '1m' }, - tags: ['apm'], - name: 'Latency threshold | synth-go', - rule_type_id: ApmRuleType.TransactionDuration, - notify_when: 'onActiveAlert', - actions: [], - }); + function createRule() { + return createApmRule({ + supertest, + name: 'Latency threshold | synth-go', + params: { + serviceName: 'synth-go', + transactionType: '', + windowSize: 99, + windowUnit: 'y', + threshold: 100, + aggregationType: AggregationType.Avg, + environment: 'testing', + }, + ruleTypeId: ApmRuleType.TransactionDuration, + }); } registry.when('Service group counts', { config: 'basic', archives: [] }, () => { @@ -89,7 +83,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { describe('with alerts', () => { let ruleId: string; before(async () => { - const { body: createdRule } = await createRule(); + const createdRule = await createRule(); ruleId = createdRule.id; await waitForActiveAlert({ ruleId, esClient, log }); }); diff --git a/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts b/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts index a8c92dfdd256e..35ee8da8ba39b 100644 --- a/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts @@ -5,10 +5,11 @@ * 2.0. */ import expect from '@kbn/expect'; -import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { AggregationType, ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { waitForActiveAlert } from '../../common/utils/wait_for_active_alert'; +import { createApmRule } from '../alerts/alerting_api_helper'; export default function ServiceAlerts({ getService }: FtrProviderContext) { const registry = getService('registry'); @@ -42,28 +43,21 @@ export default function ServiceAlerts({ getService }: FtrProviderContext) { }); } - async function createRule() { - return supertest - .post(`/api/alerting/rule`) - .set('kbn-xsrf', 'true') - .send({ - params: { - serviceName: goService, - transactionType: '', - windowSize: 99, - windowUnit: 'y', - threshold: 100, - aggregationType: 'avg', - environment: 'testing', - }, - consumer: 'apm', - schedule: { interval: '1m' }, - tags: ['apm'], - name: `Latency threshold | ${goService}`, - rule_type_id: ApmRuleType.TransactionDuration, - notify_when: 'onActiveAlert', - actions: [], - }); + function createRule() { + return createApmRule({ + supertest, + name: `Latency threshold | ${goService}`, + params: { + serviceName: goService, + transactionType: '', + windowSize: 99, + windowUnit: 'y', + threshold: 100, + aggregationType: AggregationType.Avg, + environment: 'testing', + }, + ruleTypeId: ApmRuleType.TransactionDuration, + }); } registry.when('Service alerts', { config: 'basic', archives: [] }, () => { @@ -121,7 +115,7 @@ export default function ServiceAlerts({ getService }: FtrProviderContext) { describe('with alerts', () => { let ruleId: string; before(async () => { - const { body: createdRule } = await createRule(); + const createdRule = await createRule(); ruleId = createdRule.id; await waitForActiveAlert({ ruleId, esClient, log }); }); From c6641c9b3a696699cda160b2273e14245e9eb1dc Mon Sep 17 00:00:00 2001 From: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com> Date: Mon, 13 Feb 2023 11:53:53 -0800 Subject: [PATCH 141/203] [RAM][Flapping] Convert rule flapping settings API to snake case (#150951) ## Summary Resolves: https://github.com/elastic/kibana/issues/150623 Convert the rule flapping settings API properties from camel case to snake case. The properties are rewritten once it hits the application code to camel case again. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../routes/get_flapping_settings.test.ts | 12 ++++- .../server/routes/get_flapping_settings.ts | 24 ++++++++-- .../routes/update_flapping_settings.test.ts | 37 ++++++++++----- .../server/routes/update_flapping_settings.ts | 46 ++++++++++++++++--- .../.storybook/context/http.ts | 4 +- .../lib/rule_api/get_flapping_settings.ts | 16 ++++++- .../lib/rule_api/update_flapping_settings.ts | 24 ++++++++-- .../common/lib/reset_rules_settings.ts | 6 ++- .../tests/alerting/get_flapping_settings.ts | 14 +++--- .../alerting/update_flapping_settings.ts | 40 ++++++++-------- .../tests/alerting/group1/event_log.ts | 8 ++-- .../triggers_actions_ui/rules_settings.ts | 4 +- 12 files changed, 173 insertions(+), 62 deletions(-) diff --git a/x-pack/plugins/alerting/server/routes/get_flapping_settings.test.ts b/x-pack/plugins/alerting/server/routes/get_flapping_settings.test.ts index 156ab604fb905..80354da80b784 100644 --- a/x-pack/plugins/alerting/server/routes/get_flapping_settings.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_flapping_settings.test.ts @@ -58,6 +58,16 @@ describe('getFlappingSettingsRoute', () => { await handler(context, req, res); expect(rulesSettingsClient.flapping().get).toHaveBeenCalledTimes(1); - expect(res.ok).toHaveBeenCalled(); + expect(res.ok).toHaveBeenCalledWith({ + body: expect.objectContaining({ + enabled: true, + look_back_window: 10, + status_change_threshold: 10, + created_by: 'test name', + updated_by: 'test name', + created_at: expect.any(String), + updated_at: expect.any(String), + }), + }); }); }); diff --git a/x-pack/plugins/alerting/server/routes/get_flapping_settings.ts b/x-pack/plugins/alerting/server/routes/get_flapping_settings.ts index 6ae039032994d..5d4795d664ed5 100644 --- a/x-pack/plugins/alerting/server/routes/get_flapping_settings.ts +++ b/x-pack/plugins/alerting/server/routes/get_flapping_settings.ts @@ -8,8 +8,26 @@ import { IRouter } from '@kbn/core/server'; import { ILicenseState } from '../lib'; import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; -import { verifyAccessAndContext } from './lib'; -import { API_PRIVILEGES } from '../../common'; +import { verifyAccessAndContext, RewriteResponseCase } from './lib'; +import { API_PRIVILEGES, RulesSettingsFlapping } from '../../common'; + +const rewriteBodyRes: RewriteResponseCase = ({ + lookBackWindow, + statusChangeThreshold, + createdBy, + updatedBy, + createdAt, + updatedAt, + ...rest +}) => ({ + ...rest, + look_back_window: lookBackWindow, + status_change_threshold: statusChangeThreshold, + created_by: createdBy, + updated_by: updatedBy, + created_at: createdAt, + updated_at: updatedAt, +}); export const getFlappingSettingsRoute = ( router: IRouter, @@ -27,7 +45,7 @@ export const getFlappingSettingsRoute = ( verifyAccessAndContext(licenseState, async function (context, req, res) { const rulesSettingsClient = (await context.alerting).getRulesSettingsClient(); const flappingSettings = await rulesSettingsClient.flapping().get(); - return res.ok({ body: flappingSettings }); + return res.ok({ body: rewriteBodyRes(flappingSettings) }); }) ) ); diff --git a/x-pack/plugins/alerting/server/routes/update_flapping_settings.test.ts b/x-pack/plugins/alerting/server/routes/update_flapping_settings.test.ts index 28914e71e7dd3..84fb238b8509b 100644 --- a/x-pack/plugins/alerting/server/routes/update_flapping_settings.test.ts +++ b/x-pack/plugins/alerting/server/routes/update_flapping_settings.test.ts @@ -22,6 +22,16 @@ beforeEach(() => { rulesSettingsClient = rulesSettingsClientMock.create(); }); +const mockFlappingSettings = { + enabled: true, + lookBackWindow: 10, + statusChangeThreshold: 10, + createdBy: 'test name', + updatedBy: 'test name', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), +}; + describe('updateFlappingSettingsRoute', () => { test('updates flapping settings', async () => { const licenseState = licenseStateMock.create(); @@ -40,20 +50,13 @@ describe('updateFlappingSettingsRoute', () => { } `); - (rulesSettingsClient.flapping().get as jest.Mock).mockResolvedValue({ - enabled: true, - lookBackWindow: 10, - statusChangeThreshold: 10, - createdBy: 'test name', - updatedBy: 'test name', - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }); + (rulesSettingsClient.flapping().get as jest.Mock).mockResolvedValue(mockFlappingSettings); + (rulesSettingsClient.flapping().update as jest.Mock).mockResolvedValue(mockFlappingSettings); const updateResult = { enabled: false, - lookBackWindow: 6, - statusChangeThreshold: 5, + look_back_window: 6, + status_change_threshold: 5, }; const [context, req, res] = mockHandlerArguments( @@ -77,6 +80,16 @@ describe('updateFlappingSettingsRoute', () => { }, ] `); - expect(res.ok).toHaveBeenCalled(); + expect(res.ok).toHaveBeenCalledWith({ + body: expect.objectContaining({ + enabled: true, + look_back_window: 10, + status_change_threshold: 10, + created_by: 'test name', + updated_by: 'test name', + created_at: expect.any(String), + updated_at: expect.any(String), + }), + }); }); }); diff --git a/x-pack/plugins/alerting/server/routes/update_flapping_settings.ts b/x-pack/plugins/alerting/server/routes/update_flapping_settings.ts index ede33a7d36a95..6df16434d3833 100644 --- a/x-pack/plugins/alerting/server/routes/update_flapping_settings.ts +++ b/x-pack/plugins/alerting/server/routes/update_flapping_settings.ts @@ -8,14 +8,46 @@ import { IRouter } from '@kbn/core/server'; import { schema } from '@kbn/config-schema'; import { ILicenseState } from '../lib'; -import { verifyAccessAndContext } from './lib'; +import { verifyAccessAndContext, RewriteResponseCase, RewriteRequestCase } from './lib'; import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; -import { API_PRIVILEGES } from '../../common'; +import { + API_PRIVILEGES, + RulesSettingsFlapping, + RulesSettingsFlappingProperties, +} from '../../common'; const bodySchema = schema.object({ enabled: schema.boolean(), - lookBackWindow: schema.number(), - statusChangeThreshold: schema.number(), + look_back_window: schema.number(), + status_change_threshold: schema.number(), +}); + +const rewriteQueryReq: RewriteRequestCase = ({ + look_back_window: lookBackWindow, + status_change_threshold: statusChangeThreshold, + ...rest +}) => ({ + ...rest, + lookBackWindow, + statusChangeThreshold, +}); + +const rewriteBodyRes: RewriteResponseCase = ({ + lookBackWindow, + statusChangeThreshold, + createdBy, + updatedBy, + createdAt, + updatedAt, + ...rest +}) => ({ + ...rest, + look_back_window: lookBackWindow, + status_change_threshold: statusChangeThreshold, + created_by: createdBy, + updated_by: updatedBy, + created_at: createdAt, + updated_at: updatedAt, }); export const updateFlappingSettingsRoute = ( @@ -36,10 +68,12 @@ export const updateFlappingSettingsRoute = ( verifyAccessAndContext(licenseState, async function (context, req, res) { const rulesSettingsClient = (await context.alerting).getRulesSettingsClient(); - const updatedFlappingSettings = await rulesSettingsClient.flapping().update(req.body); + const updatedFlappingSettings = await rulesSettingsClient + .flapping() + .update(rewriteQueryReq(req.body)); return res.ok({ - body: updatedFlappingSettings, + body: updatedFlappingSettings && rewriteBodyRes(updatedFlappingSettings), }); }) ) diff --git a/x-pack/plugins/triggers_actions_ui/.storybook/context/http.ts b/x-pack/plugins/triggers_actions_ui/.storybook/context/http.ts index 69e1cf2f64b91..ba7cc79901801 100644 --- a/x-pack/plugins/triggers_actions_ui/.storybook/context/http.ts +++ b/x-pack/plugins/triggers_actions_ui/.storybook/context/http.ts @@ -279,8 +279,8 @@ const rulesSettingsGetResponse = (path: string) => { if (path.endsWith('/settings/_flapping')) { return { enabled: true, - lookBackWindow: 20, - statusChangeThreshold: 4, + look_back_window: 20, + status_change_threshold: 4, }; } }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_flapping_settings.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_flapping_settings.ts index 68947de984fb4..931b1037ef729 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_flapping_settings.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/get_flapping_settings.ts @@ -6,11 +6,23 @@ */ import { HttpSetup } from '@kbn/core/public'; +import { AsApiContract, RewriteRequestCase } from '@kbn/actions-plugin/common'; import { RulesSettingsFlapping } from '@kbn/alerting-plugin/common'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; -export const getFlappingSettings = ({ http }: { http: HttpSetup }) => { - return http.get( +const rewriteBodyRes: RewriteRequestCase = ({ + look_back_window: lookBackWindow, + status_change_threshold: statusChangeThreshold, + ...rest +}: any) => ({ + ...rest, + lookBackWindow, + statusChangeThreshold, +}); + +export const getFlappingSettings = async ({ http }: { http: HttpSetup }) => { + const res = await http.get>( `${INTERNAL_BASE_ALERTING_API_PATH}/rules/settings/_flapping` ); + return rewriteBodyRes(res); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_flapping_settings.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_flapping_settings.ts index f38393b591d72..9e03da7e6e100 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_flapping_settings.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/update_flapping_settings.ts @@ -10,9 +10,20 @@ import { RulesSettingsFlapping, RulesSettingsFlappingProperties, } from '@kbn/alerting-plugin/common'; +import { AsApiContract, RewriteRequestCase } from '@kbn/actions-plugin/common'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; -export const updateFlappingSettings = ({ +const rewriteBodyRes: RewriteRequestCase = ({ + look_back_window: lookBackWindow, + status_change_threshold: statusChangeThreshold, + ...rest +}: any) => ({ + ...rest, + lookBackWindow, + statusChangeThreshold, +}); + +export const updateFlappingSettings = async ({ http, flappingSettings, }: { @@ -21,14 +32,21 @@ export const updateFlappingSettings = ({ }) => { let body: string; try { - body = JSON.stringify(flappingSettings); + body = JSON.stringify({ + enabled: flappingSettings.enabled, + look_back_window: flappingSettings.lookBackWindow, + status_change_threshold: flappingSettings.statusChangeThreshold, + }); } catch (e) { throw new Error(`Unable to parse flapping settings update params: ${e}`); } - return http.post( + + const res = await http.post>( `${INTERNAL_BASE_ALERTING_API_PATH}/rules/settings/_flapping`, { body, } ); + + return rewriteBodyRes(res); }; diff --git a/x-pack/test/alerting_api_integration/common/lib/reset_rules_settings.ts b/x-pack/test/alerting_api_integration/common/lib/reset_rules_settings.ts index b1b24856e9ef8..17ce4985e1f0c 100644 --- a/x-pack/test/alerting_api_integration/common/lib/reset_rules_settings.ts +++ b/x-pack/test/alerting_api_integration/common/lib/reset_rules_settings.ts @@ -14,6 +14,10 @@ export const resetRulesSettings = (supertest: any, space: string) => { .post(`${getUrlPrefix(space)}/internal/alerting/rules/settings/_flapping`) .set('kbn-xsrf', 'foo') .auth(Superuser.username, Superuser.password) - .send(DEFAULT_FLAPPING_SETTINGS) + .send({ + enabled: DEFAULT_FLAPPING_SETTINGS.enabled, + look_back_window: DEFAULT_FLAPPING_SETTINGS.lookBackWindow, + status_change_threshold: DEFAULT_FLAPPING_SETTINGS.statusChangeThreshold, + }) .expect(200); }; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_flapping_settings.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_flapping_settings.ts index 7bc307f41e6d4..386e32b8e5778 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_flapping_settings.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_flapping_settings.ts @@ -51,14 +51,16 @@ export default function getFlappingSettingsTests({ getService }: FtrProviderCont case 'space_1_all at space1': expect(response.statusCode).to.eql(200); expect(response.body.enabled).to.eql(DEFAULT_FLAPPING_SETTINGS.enabled); - expect(response.body.lookBackWindow).to.eql(DEFAULT_FLAPPING_SETTINGS.lookBackWindow); - expect(response.body.statusChangeThreshold).to.eql( + expect(response.body.look_back_window).to.eql( + DEFAULT_FLAPPING_SETTINGS.lookBackWindow + ); + expect(response.body.status_change_threshold).to.eql( DEFAULT_FLAPPING_SETTINGS.statusChangeThreshold ); - expect(response.body.createdBy).to.be.a('string'); - expect(response.body.updatedBy).to.be.a('string'); - expect(Date.parse(response.body.createdAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan(0); + expect(response.body.created_by).to.be.a('string'); + expect(response.body.updated_by).to.be.a('string'); + expect(Date.parse(response.body.created_at)).to.be.greaterThan(0); + expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_flapping_settings.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_flapping_settings.ts index 93659256d2e97..a4d39ad4be89b 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_flapping_settings.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_flapping_settings.ts @@ -30,8 +30,8 @@ export default function updateFlappingSettingsTest({ getService }: FtrProviderCo .auth(user.username, user.password) .send({ enabled: false, - lookBackWindow: 20, - statusChangeThreshold: 20, + look_back_window: 20, + status_change_threshold: 20, }); switch (scenario.id) { @@ -51,12 +51,12 @@ export default function updateFlappingSettingsTest({ getService }: FtrProviderCo case 'space_1_all at space1': expect(response.statusCode).to.eql(200); expect(response.body.enabled).to.eql(false); - expect(response.body.lookBackWindow).to.eql(20); - expect(response.body.statusChangeThreshold).to.eql(20); - expect(response.body.createdBy).to.eql(user.username); - expect(response.body.updatedBy).to.eql(user.username); - expect(Date.parse(response.body.createdAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan(0); + expect(response.body.look_back_window).to.eql(20); + expect(response.body.status_change_threshold).to.eql(20); + expect(response.body.created_by).to.eql(user.username); + expect(response.body.updated_by).to.eql(user.username); + expect(Date.parse(response.body.created_at)).to.be.greaterThan(0); + expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -72,8 +72,8 @@ export default function updateFlappingSettingsTest({ getService }: FtrProviderCo .auth(Superuser.username, Superuser.password) .send({ enabled: true, - lookBackWindow: 200, - statusChangeThreshold: 200, + look_back_window: 200, + status_change_threshold: 200, }) .expect(400); @@ -87,8 +87,8 @@ export default function updateFlappingSettingsTest({ getService }: FtrProviderCo .auth(Superuser.username, Superuser.password) .send({ enabled: true, - lookBackWindow: 20, - statusChangeThreshold: 200, + look_back_window: 20, + status_change_threshold: 200, }) .expect(400); @@ -102,8 +102,8 @@ export default function updateFlappingSettingsTest({ getService }: FtrProviderCo .auth(Superuser.username, Superuser.password) .send({ enabled: true, - lookBackWindow: 5, - statusChangeThreshold: 10, + look_back_window: 5, + status_change_threshold: 10, }) .expect(400); @@ -121,14 +121,14 @@ export default function updateFlappingSettingsTest({ getService }: FtrProviderCo .auth(Superuser.username, Superuser.password) .send({ enabled: false, - lookBackWindow: 20, - statusChangeThreshold: 20, + look_back_window: 20, + status_change_threshold: 20, }); expect(postResponse.statusCode).to.eql(200); expect(postResponse.body.enabled).to.eql(false); - expect(postResponse.body.lookBackWindow).to.eql(20); - expect(postResponse.body.statusChangeThreshold).to.eql(20); + expect(postResponse.body.look_back_window).to.eql(20); + expect(postResponse.body.status_change_threshold).to.eql(20); // Get the rules settings in space2 const getResponse = await supertestWithoutAuth @@ -137,8 +137,8 @@ export default function updateFlappingSettingsTest({ getService }: FtrProviderCo expect(getResponse.statusCode).to.eql(200); expect(getResponse.body.enabled).to.eql(true); - expect(getResponse.body.lookBackWindow).to.eql(20); - expect(getResponse.body.statusChangeThreshold).to.eql(4); + expect(getResponse.body.look_back_window).to.eql(20); + expect(getResponse.body.status_change_threshold).to.eql(4); }); }); }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts index 5525631c2a534..6574c2164b06c 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/event_log.ts @@ -546,8 +546,8 @@ export default function eventLogTests({ getService }: FtrProviderContext) { .auth('superuser', 'superuser') .send({ enabled: true, - lookBackWindow: 3, - statusChangeThreshold: 2, + look_back_window: 3, + status_change_threshold: 2, }) .expect(200); const { body: createdAction } = await supertest @@ -630,8 +630,8 @@ export default function eventLogTests({ getService }: FtrProviderContext) { .auth('superuser', 'superuser') .send({ enabled: true, - lookBackWindow: 3, - statusChangeThreshold: 2, + look_back_window: 3, + status_change_threshold: 2, }) .expect(200); const { body: createdAction } = await supertest diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts index 6b4297f2dc153..56b6d08253ec4 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts @@ -47,8 +47,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { .set('kbn-xsrf', 'foo') .send({ enabled: true, - lookBackWindow: 10, - statusChangeThreshold: 10, + look_back_window: 10, + status_change_threshold: 10, }) .expect(200); }); From 6bd55dab203f4df8286cf3dc50bb1ee4a79419d9 Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Mon, 13 Feb 2023 16:09:23 -0500 Subject: [PATCH 142/203] [Response Ops][Alerting] Adding ability for rule types to specify custom formatting for `getSummarizedAlerts` function (#150829) Resolves https://github.com/elastic/kibana/issues/150776 ## Summary As part of the [POC to onboard detection rules onto alert summaries](https://github.com/elastic/kibana/pull/147539/files), we uncovered a need to allow rule types to specify a custom format function for the alerts returned from the `getSummarizedAlerts` function. This will allow detection rules to perform some custom transformations before detection alerts are made available for notifications. This PR adds the necessary hook that can be used later on. --- .../create_get_summarized_alerts_fn.test.ts | 341 +++++++++++++++++- .../utils/create_get_summarized_alerts_fn.ts | 70 ++-- 2 files changed, 386 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.test.ts b/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.test.ts index 387bd0174dbc4..597d6f056fa15 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.test.ts @@ -9,6 +9,7 @@ import { RuleDataClientMock, } from '../rule_data_client/rule_data_client.mock'; import { + ALERT_ACTION_GROUP, ALERT_END, ALERT_INSTANCE_ID, ALERT_RULE_EXECUTION_UUID, @@ -18,7 +19,7 @@ import { EVENT_ACTION, TIMESTAMP, } from '../../common/technical_rule_data_field_names'; -import { createGetSummarizedAlertsFn } from './create_get_summarized_alerts_fn'; +import { AlertDocument, createGetSummarizedAlertsFn } from './create_get_summarized_alerts_fn'; describe('createGetSummarizedAlertsFn', () => { let ruleDataClientMock: RuleDataClientMock; @@ -1644,6 +1645,344 @@ describe('createGetSummarizedAlertsFn', () => { expect(summarizedAlerts.recovered.data).toEqual([]); }); + it('creates function that uses a custom format alerts function if defined', async () => { + ruleDataClientMock.getReader().search.mockResolvedValueOnce({ + hits: { + total: { + value: 6, + }, + hits: [ + { + _id: '1', + _index: '.alerts-default-000001', + _source: { + [TIMESTAMP]: '2020-01-01T12:00:00.000Z', + [ALERT_RULE_EXECUTION_UUID]: 'abc', + [ALERT_RULE_UUID]: 'rule-id', + [ALERT_INSTANCE_ID]: 'TEST_ALERT_3', + [ALERT_UUID]: 'uuid1', + kibana: { + alert: { + instance: { + id: 'TEST_ALERT_3', + }, + rule: { + execution: { + uuid: 'abc', + }, + }, + uuid: 'uuid1', + }, + }, + }, + }, + { + _id: '2', + _index: '.alerts-default-000001', + _source: { + [TIMESTAMP]: '2020-01-01T12:00:00.000Z', + [ALERT_RULE_EXECUTION_UUID]: 'abc', + [ALERT_RULE_UUID]: 'rule-id', + [ALERT_INSTANCE_ID]: 'TEST_ALERT_4', + [ALERT_UUID]: 'uuid2', + kibana: { + alert: { + instance: { + id: 'TEST_ALERT_4', + }, + rule: { + execution: { + uuid: 'abc', + }, + }, + uuid: 'uuid2', + }, + }, + }, + }, + { + _id: '3', + _index: '.alerts-default-000001', + _source: { + [TIMESTAMP]: '2020-01-01T12:10:00.000Z', + [ALERT_RULE_EXECUTION_UUID]: 'abc', + [ALERT_RULE_UUID]: 'rule-id', + [ALERT_INSTANCE_ID]: 'TEST_ALERT_1', + [ALERT_UUID]: 'uuid3', + kibana: { + alert: { + instance: { + id: 'TEST_ALERT_1', + }, + rule: { + execution: { + uuid: 'abc', + }, + }, + uuid: 'uuid3', + }, + }, + }, + }, + { + _id: '4', + _index: '.alerts-default-000001', + _source: { + [TIMESTAMP]: '2020-01-01T12:20:00.000Z', + [ALERT_RULE_EXECUTION_UUID]: 'abc', + [ALERT_RULE_UUID]: 'rule-id', + [ALERT_INSTANCE_ID]: 'TEST_ALERT_2', + [ALERT_UUID]: 'uuid4', + kibana: { + alert: { + instance: { + id: 'TEST_ALERT_2', + }, + rule: { + execution: { + uuid: 'abc', + }, + }, + uuid: 'uuid4', + }, + }, + }, + }, + { + _id: '5', + _index: '.alerts-default-000001', + _source: { + [TIMESTAMP]: '2020-01-01T12:00:00.000Z', + [ALERT_RULE_EXECUTION_UUID]: 'abc', + [ALERT_RULE_UUID]: 'rule-id', + [ALERT_INSTANCE_ID]: 'TEST_ALERT_5', + [ALERT_UUID]: 'uuid5', + kibana: { + alert: { + instance: { + id: 'TEST_ALERT_5', + }, + rule: { + execution: { + uuid: 'abc', + }, + }, + uuid: 'uuid5', + }, + }, + }, + }, + { + _id: '6', + _index: '.alerts-default-000001', + _source: { + [TIMESTAMP]: '2020-01-01T12:20:00.000Z', + [ALERT_RULE_EXECUTION_UUID]: 'abc', + [ALERT_RULE_UUID]: 'rule-id', + [ALERT_INSTANCE_ID]: 'TEST_ALERT_9', + [ALERT_UUID]: 'uuid6', + kibana: { + alert: { + instance: { + id: 'TEST_ALERT_9', + }, + rule: { + execution: { + uuid: 'abc', + }, + }, + uuid: 'uuid6', + }, + }, + }, + }, + ], + }, + } as any); + const getSummarizedAlertsFn = createGetSummarizedAlertsFn({ + ruleDataClient: ruleDataClientMock, + useNamespace: true, + isLifecycleAlert: false, + formatAlert: (alert: AlertDocument) => { + return { + ...alert, + [ALERT_ACTION_GROUP]: 'boopboopdedoo', + }; + }, + })(); + + const summarizedAlerts = await getSummarizedAlertsFn({ + start: new Date('2020-01-01T11:00:00.000Z'), + end: new Date('2020-01-01T12:25:00.000Z'), + ruleId: 'rule-id', + spaceId: 'space-id', + excludedAlertInstanceIds: ['TEST_ALERT_10'], + }); + expect(ruleDataClientMock.getReader).toHaveBeenCalledWith({ namespace: 'space-id' }); + expect(ruleDataClientMock.getReader().search).toHaveBeenCalledTimes(1); + expect(ruleDataClientMock.getReader().search).toHaveBeenCalledWith({ + body: { + size: 100, + track_total_hits: true, + query: { + bool: { + filter: [ + { + range: { + [TIMESTAMP]: { + gte: '2020-01-01T11:00:00.000Z', + lt: '2020-01-01T12:25:00.000Z', + }, + }, + }, + { + term: { + [ALERT_RULE_UUID]: 'rule-id', + }, + }, + { + bool: { + must_not: { + terms: { + [ALERT_INSTANCE_ID]: ['TEST_ALERT_10'], + }, + }, + }, + }, + ], + }, + }, + }, + }); + expect(summarizedAlerts.new.count).toEqual(6); + expect(summarizedAlerts.ongoing.count).toEqual(0); + expect(summarizedAlerts.recovered.count).toEqual(0); + expect(summarizedAlerts.new.data).toEqual([ + { + _id: '1', + _index: '.alerts-default-000001', + [TIMESTAMP]: '2020-01-01T12:00:00.000Z', + kibana: { + alert: { + action_group: 'boopboopdedoo', + instance: { + id: 'TEST_ALERT_3', + }, + rule: { + execution: { + uuid: 'abc', + }, + uuid: 'rule-id', + }, + uuid: 'uuid1', + }, + }, + }, + { + _id: '2', + _index: '.alerts-default-000001', + [TIMESTAMP]: '2020-01-01T12:00:00.000Z', + kibana: { + alert: { + action_group: 'boopboopdedoo', + instance: { + id: 'TEST_ALERT_4', + }, + rule: { + execution: { + uuid: 'abc', + }, + uuid: 'rule-id', + }, + uuid: 'uuid2', + }, + }, + }, + { + _id: '3', + _index: '.alerts-default-000001', + [TIMESTAMP]: '2020-01-01T12:10:00.000Z', + kibana: { + alert: { + action_group: 'boopboopdedoo', + instance: { + id: 'TEST_ALERT_1', + }, + rule: { + execution: { + uuid: 'abc', + }, + uuid: 'rule-id', + }, + uuid: 'uuid3', + }, + }, + }, + { + _id: '4', + _index: '.alerts-default-000001', + [TIMESTAMP]: '2020-01-01T12:20:00.000Z', + kibana: { + alert: { + action_group: 'boopboopdedoo', + instance: { + id: 'TEST_ALERT_2', + }, + rule: { + execution: { + uuid: 'abc', + }, + uuid: 'rule-id', + }, + uuid: 'uuid4', + }, + }, + }, + { + _id: '5', + _index: '.alerts-default-000001', + [TIMESTAMP]: '2020-01-01T12:00:00.000Z', + kibana: { + alert: { + action_group: 'boopboopdedoo', + instance: { + id: 'TEST_ALERT_5', + }, + rule: { + execution: { + uuid: 'abc', + }, + uuid: 'rule-id', + }, + uuid: 'uuid5', + }, + }, + }, + { + _id: '6', + _index: '.alerts-default-000001', + [TIMESTAMP]: '2020-01-01T12:20:00.000Z', + kibana: { + alert: { + action_group: 'boopboopdedoo', + instance: { + id: 'TEST_ALERT_9', + }, + rule: { + execution: { + uuid: 'abc', + }, + uuid: 'rule-id', + }, + uuid: 'uuid6', + }, + }, + }, + ]); + expect(summarizedAlerts.ongoing.data).toEqual([]); + expect(summarizedAlerts.recovered.data).toEqual([]); + }); + it('throws error if search throws error', async () => { ruleDataClientMock.getReader().search.mockImplementation(() => { throw new Error('search error'); diff --git a/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.ts b/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.ts index 4754d47f236e3..95c971230317e 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.ts @@ -27,12 +27,13 @@ import { ParsedExperimentalFields } from '../../common/parse_experimental_fields import { IRuleDataClient, IRuleDataReader } from '../rule_data_client'; const MAX_ALERT_DOCS_TO_RETURN = 100; -type AlertDocument = Partial; +export type AlertDocument = Partial; interface CreateGetSummarizedAlertsFnOpts { ruleDataClient: PublicContract; useNamespace: boolean; isLifecycleAlert: boolean; + formatAlert?: (alert: AlertDocument) => AlertDocument; } export const createGetSummarizedAlertsFn = @@ -73,6 +74,7 @@ export const createGetSummarizedAlertsFn = ruleId, executionUuid: executionUuid!, isLifecycleAlert: opts.isLifecycleAlert, + formatAlert: opts.formatAlert, excludedAlertInstanceIds, }); } @@ -83,6 +85,7 @@ export const createGetSummarizedAlertsFn = start: start!, end: end!, isLifecycleAlert: opts.isLifecycleAlert, + formatAlert: opts.formatAlert, excludedAlertInstanceIds, }); }; @@ -93,6 +96,7 @@ interface GetAlertsByExecutionUuidOpts { ruleDataClientReader: IRuleDataReader; isLifecycleAlert: boolean; excludedAlertInstanceIds: string[]; + formatAlert?: (alert: AlertDocument) => AlertDocument; } const getAlertsByExecutionUuid = async ({ @@ -101,12 +105,14 @@ const getAlertsByExecutionUuid = async ({ ruleDataClientReader, isLifecycleAlert, excludedAlertInstanceIds, + formatAlert, }: GetAlertsByExecutionUuidOpts) => { if (isLifecycleAlert) { return getLifecycleAlertsByExecutionUuid({ executionUuid, ruleId, ruleDataClientReader, + formatAlert, excludedAlertInstanceIds, }); } @@ -115,6 +121,7 @@ const getAlertsByExecutionUuid = async ({ executionUuid, ruleId, ruleDataClientReader, + formatAlert, excludedAlertInstanceIds, }); }; @@ -124,6 +131,7 @@ interface GetAlertsByExecutionUuidHelperOpts { ruleId: string; ruleDataClientReader: IRuleDataReader; excludedAlertInstanceIds: string[]; + formatAlert?: (alert: AlertDocument) => AlertDocument; } const getPersistentAlertsByExecutionUuid = async ({ @@ -131,17 +139,15 @@ const getPersistentAlertsByExecutionUuid = async { // persistent alerts only create new alerts so query by execution UUID to // get all alerts created during an execution const request = getQueryByExecutionUuid(executionUuid, ruleId, excludedAlertInstanceIds); - const response = (await ruleDataClientReader.search(request)) as ESSearchResponse< - AlertDocument, - TSearchRequest - >; + const response = await doSearch(ruleDataClientReader, request, formatAlert); return { - new: getHitsWithCount(response), + new: response, ongoing: { count: 0, data: [], @@ -158,6 +164,7 @@ const getLifecycleAlertsByExecutionUuid = async ({ ruleId, ruleDataClientReader, excludedAlertInstanceIds, + formatAlert, }: GetAlertsByExecutionUuidHelperOpts) => { // lifecycle alerts assign a different action to an alert depending // on whether it is new/ongoing/recovered. query for each action in order @@ -170,13 +177,13 @@ const getLifecycleAlertsByExecutionUuid = async ({ ]; const responses = await Promise.all( - requests.map((request) => ruleDataClientReader.search(request)) + requests.map((request) => doSearch(ruleDataClientReader, request, formatAlert)) ); return { - new: getHitsWithCount(responses[0]), - ongoing: getHitsWithCount(responses[1]), - recovered: getHitsWithCount(responses[2]), + new: responses[0], + ongoing: responses[1], + recovered: responses[2], }; }; @@ -197,24 +204,35 @@ const expandFlattenedAlert = (alert: object) => { }; const getHitsWithCount = ( - response: ESSearchResponse + response: ESSearchResponse, + formatAlert?: (alert: AlertDocument) => AlertDocument ) => { return { count: (response.hits.total as SearchTotalHits).value, data: response.hits.hits.map((hit) => { const { _id, _index, _source } = hit; - const rawAlert = { + const formattedSource = formatAlert ? formatAlert(_source) : _source; + + const expandedSource = expandFlattenedAlert(formattedSource as object); + return { _id, _index, - ..._source, + ...expandedSource, }; - - return expandFlattenedAlert(rawAlert as object); }), }; }; +const doSearch = async ( + ruleDataClientReader: IRuleDataReader, + request: ESSearchRequest, + formatAlert?: (alert: AlertDocument) => AlertDocument +) => { + const response = await ruleDataClientReader.search(request); + return getHitsWithCount(response, formatAlert); +}; + const getQueryByExecutionUuid = ( executionUuid: string, ruleId: string, @@ -272,6 +290,7 @@ interface GetAlertsByTimeRangeOpts { ruleDataClientReader: IRuleDataReader; isLifecycleAlert: boolean; excludedAlertInstanceIds: string[]; + formatAlert?: (alert: AlertDocument) => AlertDocument; } const getAlertsByTimeRange = async ({ @@ -281,6 +300,7 @@ const getAlertsByTimeRange = async ({ ruleDataClientReader, isLifecycleAlert, excludedAlertInstanceIds, + formatAlert, }: GetAlertsByTimeRangeOpts) => { if (isLifecycleAlert) { return getLifecycleAlertsByTimeRange({ @@ -288,6 +308,7 @@ const getAlertsByTimeRange = async ({ end, ruleId, ruleDataClientReader, + formatAlert, excludedAlertInstanceIds, }); } @@ -297,6 +318,7 @@ const getAlertsByTimeRange = async ({ end, ruleId, ruleDataClientReader, + formatAlert, excludedAlertInstanceIds, }); }; @@ -306,6 +328,7 @@ interface GetAlertsByTimeRangeHelperOpts { end: Date; ruleId: string; ruleDataClientReader: IRuleDataReader; + formatAlert?: (alert: AlertDocument) => AlertDocument; excludedAlertInstanceIds: string[]; } @@ -320,18 +343,16 @@ const getPersistentAlertsByTimeRange = async { // persistent alerts only create new alerts so query for all alerts within the time // range and treat them as NEW const request = getQueryByTimeRange(start, end, ruleId, excludedAlertInstanceIds); - const response = (await ruleDataClientReader.search(request)) as ESSearchResponse< - AlertDocument, - TSearchRequest - >; + const response = await doSearch(ruleDataClientReader, request, formatAlert); return { - new: getHitsWithCount(response), + new: response, ongoing: { count: 0, data: [], @@ -348,6 +369,7 @@ const getLifecycleAlertsByTimeRange = async ({ end, ruleId, ruleDataClientReader, + formatAlert, excludedAlertInstanceIds, }: GetAlertsByTimeRangeHelperOpts) => { const requests = [ @@ -357,13 +379,13 @@ const getLifecycleAlertsByTimeRange = async ({ ]; const responses = await Promise.all( - requests.map((request) => ruleDataClientReader.search(request)) + requests.map((request) => doSearch(ruleDataClientReader, request, formatAlert)) ); return { - new: getHitsWithCount(responses[0]), - ongoing: getHitsWithCount(responses[1]), - recovered: getHitsWithCount(responses[2]), + new: responses[0], + ongoing: responses[1], + recovered: responses[2], }; }; From 457e13d962fdab47c8283a4b7e5c6a000ccf0bc6 Mon Sep 17 00:00:00 2001 From: JD Kurma Date: Mon, 13 Feb 2023 16:12:47 -0500 Subject: [PATCH 143/203] [Security Solution] Enrich Value List Telemetry (#149621) ## Summary Add cluster and license information to value list telemetry sent via security channel ### Checklist Delete any items that are not applicable to this PR. - [x] ~~Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~~ - [x] ~~[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials~~ - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] ~~Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/))~~ - [x] ~~Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))~~ - [x] ~~If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~~ - [x] ~~This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))~~ - [x] ~~This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers)~~ ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [x] ~~This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)~~ --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/telemetry/__mocks__/index.ts | 11 ++-- .../server/lib/telemetry/helpers.test.ts | 19 +++++-- .../server/lib/telemetry/helpers.ts | 54 ++++++++++--------- .../server/lib/telemetry/receiver.ts | 9 ++-- .../lib/telemetry/tasks/security_lists.ts | 15 +++++- .../server/lib/telemetry/types.ts | 9 +++- 6 files changed, 72 insertions(+), 45 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/__mocks__/index.ts b/x-pack/plugins/security_solution/server/lib/telemetry/__mocks__/index.ts index ced44ebfa0658..f5718895fff26 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/__mocks__/index.ts @@ -15,6 +15,7 @@ import type { PackagePolicy } from '@kbn/fleet-plugin/common/types/models/packag import { stubEndpointAlertResponse, stubProcessTree, stubFetchTimelineEvents } from './timeline'; import { stubEndpointMetricsResponse } from './metrics'; import { prebuiltRuleAlertsResponse } from './prebuilt_rule_alerts'; +import type { ESClusterInfo, ESLicense } from '../types'; export const createMockTelemetryEventsSender = ( enableTelemetry?: boolean, @@ -37,8 +38,7 @@ export const createMockTelemetryEventsSender = ( } as unknown as jest.Mocked; }; -const stubClusterInfo = { - name: 'Stub-MacBook-Pro.local', +export const stubClusterInfo: ESClusterInfo = { cluster_name: 'elasticsearch', cluster_uuid: '5Pr5PXRQQpGJUTn0czAvKQ', version: { @@ -46,24 +46,23 @@ const stubClusterInfo = { build_type: 'tar', build_hash: '38537ab4a726b42ce8f034aad78d8fca4d4f3e51', build_date: moment().toISOString(), + build_flavor: 'DEFAULT', build_snapshot: true, lucene_version: '9.2.0', minimum_wire_compatibility_version: '7.17.0', minimum_index_compatibility_version: '7.0.0', }, - tagline: 'You Know, for Search', }; -const stubLicenseInfo = { +export const stubLicenseInfo: ESLicense = { status: 'active', uid: '4a7dde08-e5f8-4e50-80f8-bc85b72b4934', type: 'trial', issue_date: moment().toISOString(), issue_date_in_millis: 1653299879146, expiry_date: moment().toISOString(), - expiry_date_in_millis: 1655891879146, + expirty_date_in_millis: 1655891879146, max_nodes: 1000, - max_resource_units: null, issued_to: 'elasticsearch', issuer: 'elasticsearch', start_date_in_millis: -1, diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/helpers.test.ts b/x-pack/plugins/security_solution/server/lib/telemetry/helpers.test.ts index cba00773453fc..29a4158a77d00 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/helpers.test.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/helpers.test.ts @@ -6,7 +6,7 @@ */ import moment from 'moment'; -import { createMockPackagePolicy } from './__mocks__'; +import { createMockPackagePolicy, stubClusterInfo, stubLicenseInfo } from './__mocks__'; import { LIST_DETECTION_RULE_EXCEPTION, LIST_ENDPOINT_EXCEPTION, @@ -21,7 +21,7 @@ import { isPackagePolicyList, templateExceptionList, addDefaultAdvancedPolicyConfigSettings, - metricsResponseToValueListMetaData, + formatValueListMetaData, tlog, setIsElasticCloudDeployment, createTaskMetric, @@ -805,10 +805,11 @@ describe('test advanced policy config overlap ', () => { describe('test metrics response to value list meta data', () => { test('can succeed when metrics response is fully populated', async () => { + jest.useFakeTimers().setSystemTime(new Date('2023-01-30')); const stubMetricResponses = { listMetricsResponse: { aggregations: { - total_value_list_count: 5, + total_value_list_count: { value: 5 }, type_breakdown: { buckets: [ { @@ -858,8 +859,12 @@ describe('test metrics response to value list meta data', () => { }, }, }; - const response = metricsResponseToValueListMetaData(stubMetricResponses); + const response = formatValueListMetaData(stubMetricResponses, stubClusterInfo, stubLicenseInfo); expect(response).toEqual({ + '@timestamp': '2023-01-30T00:00:00.000Z', + cluster_uuid: '5Pr5PXRQQpGJUTn0czAvKQ', + cluster_name: 'elasticsearch', + license_id: '4a7dde08-e5f8-4e50-80f8-bc85b72b4934', total_list_count: 5, types: [ { @@ -901,8 +906,12 @@ describe('test metrics response to value list meta data', () => { indicatorMatchMetricsResponse: {}, }; // @ts-ignore - const response = metricsResponseToValueListMetaData(stubMetricResponses); + const response = formatValueListMetaData(stubMetricResponses, stubClusterInfo, stubLicenseInfo); expect(response).toEqual({ + '@timestamp': '2023-01-30T00:00:00.000Z', + cluster_uuid: '5Pr5PXRQQpGJUTn0czAvKQ', + cluster_name: 'elasticsearch', + license_id: '4a7dde08-e5f8-4e50-80f8-bc85b72b4934', total_list_count: 0, types: [], lists: [], diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts b/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts index 9b3a847b63e28..f03621899c800 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts @@ -18,10 +18,7 @@ import type { ESLicense, ListTemplate, TelemetryEvent, - ValueListResponseAggregation, - ValueListExceptionListResponseAggregation, - ValueListItemsResponseAggregation, - ValueListIndicatorMatchResponseAggregation, + ValueListResponse, TaskMetric, } from './types'; import { @@ -241,32 +238,37 @@ export const addDefaultAdvancedPolicyConfigSettings = (policyConfig: PolicyConfi return merge(DEFAULT_ADVANCED_POLICY_CONFIG_SETTINGS, policyConfig); }; -export const metricsResponseToValueListMetaData = ({ - listMetricsResponse, - itemMetricsResponse, - exceptionListMetricsResponse, - indicatorMatchMetricsResponse, -}: { - listMetricsResponse: ValueListResponseAggregation; - itemMetricsResponse: ValueListItemsResponseAggregation; - exceptionListMetricsResponse: ValueListExceptionListResponseAggregation; - indicatorMatchMetricsResponse: ValueListIndicatorMatchResponseAggregation; -}) => ({ - total_list_count: listMetricsResponse?.aggregations?.total_value_list_count ?? 0, +export const formatValueListMetaData = ( + valueListResponse: ValueListResponse, + clusterInfo: ESClusterInfo, + licenseInfo: ESLicense | undefined +) => ({ + '@timestamp': moment().toISOString(), + cluster_uuid: clusterInfo.cluster_uuid, + cluster_name: clusterInfo.cluster_name, + license_id: licenseInfo?.uid, + total_list_count: + valueListResponse.listMetricsResponse?.aggregations?.total_value_list_count?.value ?? 0, types: - listMetricsResponse?.aggregations?.type_breakdown?.buckets.map((breakdown) => ({ - type: breakdown.key, - count: breakdown.doc_count, - })) ?? [], + valueListResponse.listMetricsResponse?.aggregations?.type_breakdown?.buckets.map( + (breakdown) => ({ + type: breakdown.key, + count: breakdown.doc_count, + }) + ) ?? [], lists: - itemMetricsResponse?.aggregations?.value_list_item_count?.buckets.map((itemCount) => ({ - id: itemCount.key, - count: itemCount.doc_count, - })) ?? [], + valueListResponse.itemMetricsResponse?.aggregations?.value_list_item_count?.buckets.map( + (itemCount) => ({ + id: itemCount.key, + count: itemCount.doc_count, + }) + ) ?? [], included_in_exception_lists_count: - exceptionListMetricsResponse?.aggregations?.vl_included_in_exception_lists_count?.value ?? 0, + valueListResponse.exceptionListMetricsResponse?.aggregations + ?.vl_included_in_exception_lists_count?.value ?? 0, used_in_indicator_match_rule_count: - indicatorMatchMetricsResponse?.aggregations?.vl_used_in_indicator_match_rule_count?.value ?? 0, + valueListResponse.indicatorMatchMetricsResponse?.aggregations + ?.vl_used_in_indicator_match_rule_count?.value ?? 0, }); export let isElasticCloudDeployment = false; diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts index e8e0e62fac045..428dd82b4f430 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts @@ -41,7 +41,6 @@ import { exceptionListItemToTelemetryEntry, trustedApplicationToTelemetryEntry, ruleExceptionListItemToTelemetryEvent, - metricsResponseToValueListMetaData, tlog, } from './helpers'; import { Fetcher } from '../../endpoint/routes/resolver/tree/utils/fetch'; @@ -55,7 +54,7 @@ import type { GetEndpointListResponse, RuleSearchResult, ExceptionListItem, - ValueListMetaData, + ValueListResponse, ValueListResponseAggregation, ValueListItemsResponseAggregation, ValueListExceptionListResponseAggregation, @@ -172,7 +171,7 @@ export interface ITelemetryReceiver { nodeIds: string[] ): Promise>>; - fetchValueListMetaData(interval: number): Promise; + fetchValueListMetaData(interval: number): Promise; } export class TelemetryReceiver implements ITelemetryReceiver { @@ -924,12 +923,12 @@ export class TelemetryReceiver implements ITelemetryReceiver { exceptionListMetrics as unknown as ValueListExceptionListResponseAggregation; const indicatorMatchMetricsResponse = indicatorMatchMetrics as unknown as ValueListIndicatorMatchResponseAggregation; - return metricsResponseToValueListMetaData({ + return { listMetricsResponse, itemMetricsResponse, exceptionListMetricsResponse, indicatorMatchMetricsResponse, - }); + }; } public async fetchClusterInfo(): Promise { diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts index 08baef614c1b8..68a6fb643e1ba 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/tasks/security_lists.ts @@ -18,7 +18,13 @@ import { TASK_METRICS_CHANNEL, } from '../constants'; import type { ESClusterInfo, ESLicense } from '../types'; -import { batchTelemetryRecords, templateExceptionList, tlog, createTaskMetric } from '../helpers'; +import { + batchTelemetryRecords, + templateExceptionList, + tlog, + createTaskMetric, + formatValueListMetaData, +} from '../helpers'; import type { ITelemetryEventsSender } from '../sender'; import type { ITelemetryReceiver } from '../receiver'; import type { TaskExecutionPeriod } from '../task'; @@ -114,9 +120,14 @@ export function createTelemetrySecurityListTaskConfig(maxTelemetryBatch: number) } // Value list meta data - const valueListMetaData = await receiver.fetchValueListMetaData( + const valueListResponse = await receiver.fetchValueListMetaData( FETCH_VALUE_LIST_META_DATA_INTERVAL_IN_HOURS ); + const valueListMetaData = formatValueListMetaData( + valueListResponse, + clusterInfo, + licenseInfo + ); tlog(logger, `Value List Meta Data: ${JSON.stringify(valueListMetaData)}`); if (valueListMetaData?.total_list_count) { await sender.sendOnDemand(TELEMETRY_CHANNEL_LISTS, [valueListMetaData]); diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/types.ts b/x-pack/plugins/security_solution/server/lib/telemetry/types.ts index 5566a118a6e90..ba61f6b85aaab 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/types.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/types.ts @@ -382,7 +382,7 @@ export interface ValueListMetaData { export interface ValueListResponseAggregation { aggregations: { - total_value_list_count: number; + total_value_list_count: { value: number }; type_breakdown: { buckets: Array<{ key: string; @@ -437,3 +437,10 @@ export interface TelemetryFilterListArtifact { exception_lists: AllowlistFields; prebuilt_rules_alerts: AllowlistFields; } + +export interface ValueListResponse { + listMetricsResponse: ValueListResponseAggregation; + itemMetricsResponse: ValueListItemsResponseAggregation; + exceptionListMetricsResponse: ValueListExceptionListResponseAggregation; + indicatorMatchMetricsResponse: ValueListIndicatorMatchResponseAggregation; +} From 17855ba5a240ce2cd60f318b49f0040d0cfabbbd Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 13 Feb 2023 15:48:28 -0600 Subject: [PATCH 144/203] [build] Fix config argument order (#151052) Snapshot builds are currently being marked as release builds in the config service. This impacts the release property in package.json snapshot builds and pull request deployments. This was introduced in https://github.com/elastic/kibana/commit/1b8581540295fde746dae6b4a09d74fb5821bfef#diff-dbea24da2a777429d025c1da037dd966d65bff2c97a7b78b82a33532f3ad06d9R63 --- src/dev/build/lib/config.test.ts | 18 ++++++++++++++++-- src/dev/build/lib/config.ts | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/dev/build/lib/config.test.ts b/src/dev/build/lib/config.test.ts index e46a1984ceac0..5f530a7f6f2d8 100644 --- a/src/dev/build/lib/config.test.ts +++ b/src/dev/build/lib/config.test.ts @@ -25,9 +25,12 @@ const versionInfo = jest.requireMock('./version_info').getVersionInfo(); expect.addSnapshotSerializer(createAbsolutePathSerializer()); -const setup = async ({ targetAllPlatforms = true }: { targetAllPlatforms?: boolean } = {}) => { +const setup = async ({ + targetAllPlatforms = true, + isRelease = true, +}: { targetAllPlatforms?: boolean; isRelease?: boolean } = {}) => { return await Config.create({ - isRelease: true, + isRelease, targetAllPlatforms, dockerContextUseLocalArtifact: false, dockerCrossCompile: false, @@ -192,6 +195,17 @@ describe('#getBuildSha()', () => { }); }); +describe('#isRelease()', () => { + it('returns true when marked as a release', async () => { + const config = await setup({ isRelease: true }); + expect(config.isRelease).toBe(true); + }); + it('returns false when not marked as a release', async () => { + const config = await setup({ isRelease: false }); + expect(config.isRelease).toBe(false); + }); +}); + describe('#resolveFromTarget()', () => { it('resolves a relative path, from the target directory', async () => { const config = await setup(); diff --git a/src/dev/build/lib/config.ts b/src/dev/build/lib/config.ts index 42e772646fb36..175a3768924ab 100644 --- a/src/dev/build/lib/config.ts +++ b/src/dev/build/lib/config.ts @@ -82,8 +82,8 @@ export class Config { private readonly dockerTag: string | null, private readonly dockerTagQualifier: string | null, private readonly dockerPush: boolean, - public readonly downloadFreshNode: boolean, public readonly isRelease: boolean, + public readonly downloadFreshNode: boolean, public readonly pluginSelector: PluginSelector ) { this.pluginFilter = getPluginPackagesFilter(this.pluginSelector); From f1046e55c17685781110a11d2842afcbd6a2efa4 Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 13 Feb 2023 15:50:45 -0600 Subject: [PATCH 145/203] [artifacts/container image] Only trigger on main branch (#151050) We only need to product container images for the most recent commit. This updates the trigger to only run on `main`. note: `skip-ci` label, this only runs on-merge and is a no-op from pull requests. --- .buildkite/scripts/steps/artifacts/docker_image_trigger.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.buildkite/scripts/steps/artifacts/docker_image_trigger.sh b/.buildkite/scripts/steps/artifacts/docker_image_trigger.sh index f76eee8986c40..0eb268e3f95f8 100755 --- a/.buildkite/scripts/steps/artifacts/docker_image_trigger.sh +++ b/.buildkite/scripts/steps/artifacts/docker_image_trigger.sh @@ -2,4 +2,7 @@ set -euo pipefail -ts-node .buildkite/scripts/steps/trigger_pipeline.ts kibana-artifacts-container-image "$BUILDKITE_BRANCH" "$BUILDKITE_COMMIT" +if [[ "$BUILDKITE_BRANCH" == "main" ]]; then + echo "--- Trigger artifacts container image pipeline" + ts-node .buildkite/scripts/steps/trigger_pipeline.ts kibana-artifacts-container-image "$BUILDKITE_BRANCH" "$BUILDKITE_COMMIT" +fi From 7d8ccd6577ea271bd053a382909a34fe5d8d3ac9 Mon Sep 17 00:00:00 2001 From: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com> Date: Mon, 13 Feb 2023 14:07:02 -0800 Subject: [PATCH 146/203] [RAM] Reduce triggers actions UI bundle size by removing unused exports (#150971) ## Summary Resolves: https://github.com/elastic/kibana/issues/151055 Reduces the triggers actions UI bundle size by about half, by removing unused exports from index files as those get bundled in the synchronous bundle even if the components importing them are lazy-loaded. ![new_bundle_size](https://user-images.githubusercontent.com/74562234/218380222-60b39a2a-dc47-4c8f-ba35-99b658b540e4.png) ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../application/components/health_check.tsx | 2 +- .../rules_settings_link.test.tsx | 4 +- .../hooks/use_fetch_rule_action_connectors.ts | 3 +- .../hooks/use_get_flapping_settings.ts | 2 +- .../application/hooks/use_load_rule_types.ts | 2 +- .../hooks/use_load_rule_types_query.ts | 2 +- .../application/hooks/use_load_tags.test.tsx | 4 +- .../application/hooks/use_load_tags_query.ts | 2 +- .../hooks/use_update_flapping_settings.ts | 2 +- .../load_execution_kpi_aggregations.ts | 2 +- .../load_execution_log_aggregations.ts | 2 +- .../public/application/lib/rule_api/index.ts | 32 ------ .../public/application/lib/run_rule.test.ts | 4 +- .../public/application/lib/run_rule.ts | 2 +- .../with_bulk_rule_api_operations.test.tsx | 108 +++++++++++++----- .../with_bulk_rule_api_operations.tsx | 51 ++++----- .../components/rule_details.test.tsx | 6 +- .../rule_details/components/rule_details.tsx | 2 +- .../sections/rule_form/rule_add.test.tsx | 11 +- .../sections/rule_form/rule_add.tsx | 3 +- .../sections/rule_form/rule_edit.test.tsx | 8 +- .../sections/rule_form/rule_edit.tsx | 3 +- .../notify_badge/notify_badge_with_api.tsx | 8 +- .../components/rule_snooze_modal.tsx | 3 +- .../rules_list/components/rules_list.test.tsx | 29 ++++- .../rules_list/components/rules_list.tsx | 18 +-- .../rules_list_bulk_delete.test.tsx | 17 ++- .../rules_list_bulk_disable.test.tsx | 17 ++- .../components/rules_list_bulk_edit.test.tsx | 24 +++- .../rules_list_bulk_enable.test.tsx | 17 ++- .../triggers_actions_ui/public/index.ts | 11 +- 31 files changed, 248 insertions(+), 153 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx index fa5c6656d5082..c274bee5eb865 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/health_check.tsx @@ -21,7 +21,7 @@ import { useHealthContext } from '../context/health_context'; import { useKibana } from '../../common/lib/kibana'; import { CenterJustifiedSpinner } from './center_justified_spinner'; import { triggersActionsUiHealth } from '../../common/lib/health_api'; -import { alertingFrameworkHealth } from '../lib/rule_api'; +import { alertingFrameworkHealth } from '../lib/rule_api/health'; interface Props { inFlyout?: boolean; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_link.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_link.test.tsx index e2e454e644ac0..17cc4ea8bca8f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_link.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_link.test.tsx @@ -14,8 +14,8 @@ import { coreMock } from '@kbn/core/public/mocks'; import { RulesSettingsFlapping } from '@kbn/alerting-plugin/common'; import { RulesSettingsLink } from './rules_settings_link'; import { useKibana } from '../../../common/lib/kibana'; -import { getFlappingSettings } from '../../lib/rule_api'; -import { updateFlappingSettings } from '../../lib/rule_api'; +import { getFlappingSettings } from '../../lib/rule_api/get_flapping_settings'; +import { updateFlappingSettings } from '../../lib/rule_api/update_flapping_settings'; jest.mock('../../../common/lib/kibana'); jest.mock('../../lib/rule_api/get_flapping_settings', () => ({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_fetch_rule_action_connectors.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_fetch_rule_action_connectors.ts index c9e1bde1ae46a..039fd963137f7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_fetch_rule_action_connectors.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_fetch_rule_action_connectors.ts @@ -7,7 +7,8 @@ import { useEffect, useState, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; -import { ActionConnector, loadAllActions } from '../..'; +import type { ActionConnector } from '../..'; +import { loadAllActions } from '../lib/action_connector_api'; import { useKibana } from '../../common/lib/kibana'; const ACTIONS_LOAD_ERROR = (errorMessage: string) => diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_flapping_settings.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_flapping_settings.ts index 23f4af9e9daa7..e3166999df9ed 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_flapping_settings.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_get_flapping_settings.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { useQuery } from '@tanstack/react-query'; import { RulesSettingsFlapping } from '@kbn/alerting-plugin/common'; import { useKibana } from '../../common/lib/kibana'; -import { getFlappingSettings } from '../lib/rule_api'; +import { getFlappingSettings } from '../lib/rule_api/get_flapping_settings'; interface UseGetFlappingSettingsProps { enabled: boolean; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts index 7382f3fbd39f2..bce0b9ec4ff66 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types.ts @@ -5,7 +5,7 @@ * 2.0. */ import { useEffect, useState, useRef } from 'react'; -import { loadRuleTypes } from '../lib/rule_api'; +import { loadRuleTypes } from '../lib/rule_api/rule_types'; import { RuleType, RuleTypeIndex } from '../../types'; import { useKibana } from '../../common/lib/kibana'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts index 0b899b80e8882..d9b1f6080c18f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_rule_types_query.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { useQuery } from '@tanstack/react-query'; import { ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common'; -import { loadRuleTypes } from '../lib/rule_api'; +import { loadRuleTypes } from '../lib/rule_api/rule_types'; import { useKibana } from '../../common/lib/kibana'; import { RuleType, RuleTypeIndex } from '../../types'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags.test.tsx index f20f087741ab9..b8704eea881a8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags.test.tsx @@ -15,12 +15,12 @@ import { waitFor } from '@testing-library/dom'; const MOCK_TAGS = ['a', 'b', 'c']; jest.mock('../../common/lib/kibana'); -jest.mock('../lib/rule_api', () => ({ +jest.mock('../lib/rule_api/aggregate', () => ({ loadRuleTags: jest.fn(), })); const useKibanaMock = useKibana as jest.Mocked; -const { loadRuleTags } = jest.requireMock('../lib/rule_api'); +const { loadRuleTags } = jest.requireMock('../lib/rule_api/aggregate'); const queryClient = new QueryClient({ defaultOptions: { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.ts index 8b4bee5deccc0..4e97c0bc52bac 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_load_tags_query.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { useQuery } from '@tanstack/react-query'; -import { loadRuleTags } from '../lib/rule_api'; +import { loadRuleTags } from '../lib/rule_api/aggregate'; import { useKibana } from '../../common/lib/kibana'; interface UseLoadTagsQueryProps { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_flapping_settings.ts b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_flapping_settings.ts index d5f978db9d3c0..ee1309a3f6582 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_flapping_settings.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/hooks/use_update_flapping_settings.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { useMutation } from '@tanstack/react-query'; import { RulesSettingsFlappingProperties } from '@kbn/alerting-plugin/common'; import { useKibana } from '../../common/lib/kibana'; -import { updateFlappingSettings } from '../lib/rule_api'; +import { updateFlappingSettings } from '../lib/rule_api/update_flapping_settings'; interface UseUpdateFlappingSettingsProps { onClose: () => void; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_kpi_aggregations.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_kpi_aggregations.ts index 34e4fca191673..c7b895b576c3f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_kpi_aggregations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_kpi_aggregations.ts @@ -8,7 +8,7 @@ import { HttpSetup } from '@kbn/core/public'; import { IExecutionKPIResult } from '@kbn/actions-plugin/common'; import { INTERNAL_BASE_ACTION_API_PATH } from '../../constants'; -import { getFilter } from '../rule_api'; +import { getFilter } from '../rule_api/get_filter'; export interface LoadGlobalConnectorExecutionKPIAggregationsProps { outcomeFilter?: string[]; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts index 210fe3ed310b3..76a96fe300359 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/load_execution_log_aggregations.ts @@ -17,7 +17,7 @@ import { INTERNAL_BASE_ACTION_API_PATH, RewriteRequestCase, } from '@kbn/actions-plugin/common'; -import { getFilter } from '../rule_api'; +import { getFilter } from '../rule_api/get_filter'; const getRenamedLog = (data: IExecutionLog) => { const { duration_ms, schedule_delay_ms, ...rest } = data; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/index.ts index 75fc27e86e773..065272682516a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/index.ts @@ -5,47 +5,15 @@ * 2.0. */ -export { alertingFrameworkHealth } from './health'; export type { LoadRuleAggregationsProps } from './aggregate_helpers'; -export { loadRuleAggregations, loadRuleTags } from './aggregate'; -export { createRule } from './create'; -export { cloneRule } from './clone'; -export { loadRule } from './get_rule'; -export { loadRuleSummary } from './rule_summary'; -export { muteAlertInstance } from './mute_alert'; -export { muteRule, muteRules } from './mute'; -export { loadRuleTypes } from './rule_types'; export type { LoadRulesProps } from './rules_helpers'; -export { loadRules } from './rules'; -export { loadRuleState } from './state'; export type { LoadExecutionLogAggregationsProps, LoadGlobalExecutionLogAggregationsProps, } from './load_execution_log_aggregations'; -export { - loadExecutionLogAggregations, - loadGlobalExecutionLogAggregations, -} from './load_execution_log_aggregations'; export type { LoadExecutionKPIAggregationsProps } from './load_execution_kpi_aggregations'; -export { loadExecutionKPIAggregations } from './load_execution_kpi_aggregations'; export type { LoadGlobalExecutionKPIAggregationsProps } from './load_global_execution_kpi_aggregations'; -export { loadGlobalExecutionKPIAggregations } from './load_global_execution_kpi_aggregations'; export type { LoadActionErrorLogProps } from './load_action_error_log'; -export { loadActionErrorLog } from './load_action_error_log'; -export { unmuteAlertInstance } from './unmute_alert'; -export { unmuteRule, unmuteRules } from './unmute'; -export { updateRule } from './update'; -export { resolveRule } from './resolve_rule'; export type { BulkSnoozeRulesProps } from './snooze'; -export { snoozeRule, bulkSnoozeRules } from './snooze'; export type { BulkUnsnoozeRulesProps } from './unsnooze'; -export { unsnoozeRule, bulkUnsnoozeRules } from './unsnooze'; export type { BulkUpdateAPIKeyProps } from './update_api_key'; -export { updateAPIKey, bulkUpdateAPIKey } from './update_api_key'; -export { runSoon } from './run_soon'; -export { bulkDeleteRules } from './bulk_delete'; -export { bulkEnableRules } from './bulk_enable'; -export { bulkDisableRules } from './bulk_disable'; -export { getFilter } from './get_filter'; -export { getFlappingSettings } from './get_flapping_settings'; -export { updateFlappingSettings } from './update_flapping_settings'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.test.ts index ee9a391521fc7..1a33a30faf25d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.test.ts @@ -8,10 +8,10 @@ import { coreMock } from '@kbn/core/public/mocks'; import { runRule } from './run_rule'; -jest.mock('./rule_api', () => ({ +jest.mock('./rule_api/run_soon', () => ({ runSoon: jest.fn(), })); -const mockRunSoon = jest.requireMock('./rule_api').runSoon; +const { runSoon: mockRunSoon } = jest.requireMock('./rule_api/run_soon'); describe('runRule', () => { const mockCoreSetup = coreMock.createSetup(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.ts index 75617a0e45111..7aa425d10e9eb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/run_rule.ts @@ -7,7 +7,7 @@ import { HttpSetup } from '@kbn/core-http-browser'; import { IToasts } from '@kbn/core-notifications-browser'; import { i18n } from '@kbn/i18n'; -import { runSoon } from './rule_api'; +import { runSoon } from './rule_api/run_soon'; export async function runRule(http: HttpSetup, toasts: IToasts, id: string) { try { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.test.tsx index 280e7f140f78f..753b3c8497fe9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.test.tsx @@ -5,18 +5,64 @@ * 2.0. */ +/* eslint-disable @typescript-eslint/no-shadow */ + import * as React from 'react'; import { shallow, mount } from 'enzyme'; import { v4 as uuidv4 } from 'uuid'; import { withBulkRuleOperations, ComponentOpts } from './with_bulk_rule_api_operations'; -import * as ruleApi from '../../../lib/rule_api'; import { SortField } from '../../../lib/rule_api/load_execution_log_aggregations'; - import { Rule } from '../../../../types'; import { useKibana } from '../../../../common/lib/kibana'; + jest.mock('../../../../common/lib/kibana'); -jest.mock('../../../lib/rule_api'); +jest.mock('../../../lib/rule_api/load_execution_log_aggregations', () => ({ + loadExecutionLogAggregations: jest.fn(), +})); +jest.mock('../../../lib/rule_api/mute', () => ({ + muteRules: jest.fn(), + muteRule: jest.fn(), +})); +jest.mock('../../../lib/rule_api/unmute', () => ({ + unmuteRules: jest.fn(), + unmuteRule: jest.fn(), +})); +jest.mock('../../../lib/rule_api/bulk_delete', () => ({ + bulkDeleteRules: jest.fn(), +})); +jest.mock('../../../lib/rule_api/bulk_enable', () => ({ + bulkEnableRules: jest.fn(), +})); +jest.mock('../../../lib/rule_api/bulk_disable', () => ({ + bulkDisableRules: jest.fn(), +})); +jest.mock('../../../lib/rule_api/get_rule', () => ({ + loadRule: jest.fn(), +})); +jest.mock('../../../lib/rule_api/resolve_rule', () => ({ + resolveRule: jest.fn(), +})); +jest.mock('../../../lib/rule_api/rule_types', () => ({ + loadRuleTypes: jest.fn(), +})); +jest.mock('../../../lib/rule_api/load_action_error_log', () => ({ + loadActionErrorLog: jest.fn(), +})); + +const { loadExecutionLogAggregations } = jest.requireMock( + '../../../lib/rule_api/load_execution_log_aggregations' +); +const { muteRules, muteRule } = jest.requireMock('../../../lib/rule_api/mute'); +const { unmuteRules, unmuteRule } = jest.requireMock('../../../lib/rule_api/unmute'); +const { bulkDeleteRules } = jest.requireMock('../../../lib/rule_api/bulk_delete'); +const { bulkEnableRules } = jest.requireMock('../../../lib/rule_api/bulk_enable'); +const { bulkDisableRules } = jest.requireMock('../../../lib/rule_api/bulk_disable'); +const { loadRule } = jest.requireMock('../../../lib/rule_api/get_rule'); +const { resolveRule } = jest.requireMock('../../../lib/rule_api/resolve_rule'); +const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); +const { loadActionErrorLog } = jest.requireMock('../../../lib/rule_api/load_action_error_log'); + const useKibanaMock = useKibana as jest.Mocked; describe('with_bulk_rule_api_operations', () => { @@ -56,8 +102,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.muteRule).toHaveBeenCalledTimes(1); - expect(ruleApi.muteRule).toHaveBeenCalledWith({ id: rule.id, http }); + expect(muteRule).toHaveBeenCalledTimes(1); + expect(muteRule).toHaveBeenCalledWith({ id: rule.id, http }); }); it('unmuteRule calls the unmuteRule api', () => { @@ -71,8 +117,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.unmuteRule).toHaveBeenCalledTimes(1); - expect(ruleApi.unmuteRule).toHaveBeenCalledWith({ id: rule.id, http }); + expect(unmuteRule).toHaveBeenCalledTimes(1); + expect(unmuteRule).toHaveBeenCalledWith({ id: rule.id, http }); }); it('enableRule calls the muteRules api', () => { @@ -86,8 +132,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.bulkEnableRules).toHaveBeenCalledTimes(1); - expect(ruleApi.bulkEnableRules).toHaveBeenCalledWith({ ids: [rule.id], http }); + expect(bulkEnableRules).toHaveBeenCalledTimes(1); + expect(bulkEnableRules).toHaveBeenCalledWith({ ids: [rule.id], http }); }); it('disableRule calls the disableRule api', () => { @@ -101,8 +147,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.bulkDisableRules).toHaveBeenCalledTimes(1); - expect(ruleApi.bulkDisableRules).toHaveBeenCalledWith({ ids: [rule.id], http }); + expect(bulkDisableRules).toHaveBeenCalledTimes(1); + expect(bulkDisableRules).toHaveBeenCalledWith({ ids: [rule.id], http }); }); // bulk rules @@ -117,8 +163,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.muteRules).toHaveBeenCalledTimes(1); - expect(ruleApi.muteRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id], http }); + expect(muteRules).toHaveBeenCalledTimes(1); + expect(muteRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id], http }); }); it('unmuteRules calls the unmuteRules api', () => { @@ -132,8 +178,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.unmuteRules).toHaveBeenCalledTimes(1); - expect(ruleApi.unmuteRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id], http }); + expect(unmuteRules).toHaveBeenCalledTimes(1); + expect(unmuteRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id], http }); }); it('enableRules calls the muteRuless api', () => { @@ -155,8 +201,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.bulkEnableRules).toHaveBeenCalledTimes(1); - expect(ruleApi.bulkEnableRules).toHaveBeenCalledWith({ + expect(bulkEnableRules).toHaveBeenCalledTimes(1); + expect(bulkEnableRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id, rules[2].id], http, }); @@ -177,8 +223,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.bulkDisableRules).toHaveBeenCalledTimes(1); - expect(ruleApi.bulkDisableRules).toHaveBeenCalledWith({ + expect(bulkDisableRules).toHaveBeenCalledTimes(1); + expect(bulkDisableRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id], http, }); @@ -199,8 +245,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.bulkDeleteRules).toHaveBeenCalledTimes(1); - expect(ruleApi.bulkDeleteRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id], http }); + expect(bulkDeleteRules).toHaveBeenCalledTimes(1); + expect(bulkDeleteRules).toHaveBeenCalledWith({ ids: [rules[0].id, rules[1].id], http }); }); it('loadRule calls the loadRule api', () => { @@ -214,8 +260,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.loadRule).toHaveBeenCalledTimes(1); - expect(ruleApi.loadRule).toHaveBeenCalledWith({ ruleId, http }); + expect(loadRule).toHaveBeenCalledTimes(1); + expect(loadRule).toHaveBeenCalledWith({ ruleId, http }); }); it('resolveRule calls the resolveRule api', () => { @@ -229,8 +275,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.resolveRule).toHaveBeenCalledTimes(1); - expect(ruleApi.resolveRule).toHaveBeenCalledWith({ ruleId, http }); + expect(resolveRule).toHaveBeenCalledTimes(1); + expect(resolveRule).toHaveBeenCalledWith({ ruleId, http }); }); it('loadRuleTypes calls the loadRuleTypes api', () => { @@ -243,8 +289,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.loadRuleTypes).toHaveBeenCalledTimes(1); - expect(ruleApi.loadRuleTypes).toHaveBeenCalledWith({ http }); + expect(loadRuleTypes).toHaveBeenCalledTimes(1); + expect(loadRuleTypes).toHaveBeenCalledWith({ http }); }); it('loadExecutionLogAggregations calls the loadExecutionLogAggregations API', () => { @@ -274,8 +320,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.loadExecutionLogAggregations).toHaveBeenCalledTimes(1); - expect(ruleApi.loadExecutionLogAggregations).toHaveBeenCalledWith({ + expect(loadExecutionLogAggregations).toHaveBeenCalledTimes(1); + expect(loadExecutionLogAggregations).toHaveBeenCalledWith({ ...callProps, http, }); @@ -307,8 +353,8 @@ describe('with_bulk_rule_api_operations', () => { const component = mount(); component.find('button').simulate('click'); - expect(ruleApi.loadActionErrorLog).toHaveBeenCalledTimes(1); - expect(ruleApi.loadActionErrorLog).toHaveBeenCalledWith({ + expect(loadActionErrorLog).toHaveBeenCalledTimes(1); + expect(loadActionErrorLog).toHaveBeenCalledWith({ ...callProps, http, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx index 4fe559e090550..ecb431ad3ba93 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/with_bulk_rule_api_operations.tsx @@ -24,40 +24,39 @@ import { BulkOperationResponse, BulkOperationAttributesWithoutHttp, } from '../../../../types'; -import { - muteRules, - unmuteRules, - muteRule, - unmuteRule, - muteAlertInstance, - unmuteAlertInstance, - loadRule, - loadRuleState, - loadRuleSummary, - loadRuleTypes, - alertingFrameworkHealth, - resolveRule, - loadExecutionLogAggregations, - loadGlobalExecutionLogAggregations, +import type { LoadExecutionLogAggregationsProps, LoadGlobalExecutionLogAggregationsProps, - loadActionErrorLog, LoadActionErrorLogProps, - snoozeRule, - bulkSnoozeRules, BulkSnoozeRulesProps, - unsnoozeRule, - loadExecutionKPIAggregations, LoadExecutionKPIAggregationsProps, - loadGlobalExecutionKPIAggregations, LoadGlobalExecutionKPIAggregationsProps, - bulkUnsnoozeRules, BulkUnsnoozeRulesProps, - cloneRule, - bulkDeleteRules, - bulkEnableRules, - bulkDisableRules, } from '../../../lib/rule_api'; +import { alertingFrameworkHealth } from '../../../lib/rule_api/health'; +import { cloneRule } from '../../../lib/rule_api/clone'; +import { loadRule } from '../../../lib/rule_api/get_rule'; +import { loadRuleSummary } from '../../../lib/rule_api/rule_summary'; +import { muteAlertInstance } from '../../../lib/rule_api/mute_alert'; +import { loadRuleTypes } from '../../../lib/rule_api/rule_types'; +import { + loadExecutionLogAggregations, + loadGlobalExecutionLogAggregations, +} from '../../../lib/rule_api/load_execution_log_aggregations'; +import { muteRules, muteRule } from '../../../lib/rule_api/mute'; +import { unmuteRules, unmuteRule } from '../../../lib/rule_api/unmute'; +import { loadRuleState } from '../../../lib/rule_api/state'; +import { loadExecutionKPIAggregations } from '../../../lib/rule_api/load_execution_kpi_aggregations'; +import { loadGlobalExecutionKPIAggregations } from '../../../lib/rule_api/load_global_execution_kpi_aggregations'; +import { loadActionErrorLog } from '../../../lib/rule_api/load_action_error_log'; +import { unmuteAlertInstance } from '../../../lib/rule_api/unmute_alert'; +import { resolveRule } from '../../../lib/rule_api/resolve_rule'; +import { snoozeRule, bulkSnoozeRules } from '../../../lib/rule_api/snooze'; +import { unsnoozeRule, bulkUnsnoozeRules } from '../../../lib/rule_api/unsnooze'; +import { bulkDeleteRules } from '../../../lib/rule_api/bulk_delete'; +import { bulkEnableRules } from '../../../lib/rule_api/bulk_enable'; +import { bulkDisableRules } from '../../../lib/rule_api/bulk_disable'; + import { useKibana } from '../../../../common/lib/kibana'; export interface ComponentOpts { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.test.tsx index 4318412fe5261..a57b896a95902 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.test.tsx @@ -44,11 +44,11 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadAllActions: jest.fn().mockResolvedValue([]), })); -jest.mock('../../../lib/rule_api', () => ({ +jest.mock('../../../lib/rule_api/update_api_key', () => ({ bulkUpdateAPIKey: jest.fn(), - deleteRules: jest.fn(), })); -const { bulkUpdateAPIKey } = jest.requireMock('../../../lib/rule_api'); + +const { bulkUpdateAPIKey } = jest.requireMock('../../../lib/rule_api/update_api_key'); jest.mock('../../../lib/capabilities', () => ({ hasAllPrivilege: jest.fn(() => true), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.tsx index 0e06036b2b32e..acc37089f4b7d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule_details.tsx @@ -27,7 +27,7 @@ import { toMountPoint } from '@kbn/kibana-react-plugin/public'; import { RuleExecutionStatusErrorReasons, parseDuration } from '@kbn/alerting-plugin/common'; import { getRuleDetailsRoute } from '@kbn/rule-data-utils'; import { UpdateApiKeyModalConfirmation } from '../../../components/update_api_key_modal_confirmation'; -import { bulkUpdateAPIKey } from '../../../lib/rule_api'; +import { bulkUpdateAPIKey } from '../../../lib/rule_api/update_api_key'; import { RulesDeleteModalConfirmation } from '../../../components/rules_delete_modal_confirmation'; import { RuleActionsPopover } from './rule_actions_popover'; import { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.test.tsx index 5467dc38c35fb..d3e989bd135a0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.test.tsx @@ -13,7 +13,8 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiFormLabel } from '@elastic/eui'; import { coreMock } from '@kbn/core/public/mocks'; import RuleAdd from './rule_add'; -import { createRule, alertingFrameworkHealth } from '../../lib/rule_api'; +import { createRule } from '../../lib/rule_api/create'; +import { alertingFrameworkHealth } from '../../lib/rule_api/health'; import { actionTypeRegistryMock } from '../../action_type_registry.mock'; import { Rule, @@ -32,9 +33,13 @@ import { loadActionTypes, loadAllActions } from '../../lib/action_connector_api' jest.mock('../../../common/lib/kibana'); -jest.mock('../../lib/rule_api', () => ({ +jest.mock('../../lib/rule_api/rule_types', () => ({ loadRuleTypes: jest.fn(), +})); +jest.mock('../../lib/rule_api/create', () => ({ createRule: jest.fn(), +})); +jest.mock('../../lib/rule_api/health', () => ({ alertingFrameworkHealth: jest.fn(() => ({ isSufficientlySecure: true, hasPermanentEncryptionKey: true, @@ -88,7 +93,7 @@ describe('rule_add', () => { ) { const useKibanaMock = useKibana as jest.Mocked; const mocks = coreMock.createSetup(); - const { loadRuleTypes } = jest.requireMock('../../lib/rule_api'); + const { loadRuleTypes } = jest.requireMock('../../lib/rule_api/rule_types'); const ruleTypes = [ { id: 'my-rule-type', diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx index 76bef4c35788d..ec1f298b58ba0 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_add.tsx @@ -23,7 +23,8 @@ import { import { RuleForm } from './rule_form'; import { getRuleActionErrors, getRuleErrors, isValidRule } from './rule_errors'; import { ruleReducer, InitialRule, InitialRuleReducer } from './rule_reducer'; -import { createRule, loadRuleTypes } from '../../lib/rule_api'; +import { createRule } from '../../lib/rule_api/create'; +import { loadRuleTypes } from '../../lib/rule_api/rule_types'; import { HealthCheck } from '../../components/health_check'; import { ConfirmRuleSave } from './confirm_rule_save'; import { ConfirmRuleClose } from './confirm_rule_close'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.test.tsx index 5830ab2bd9312..57ba467c79762 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.test.tsx @@ -21,9 +21,13 @@ const actionTypeRegistry = actionTypeRegistryMock.create(); const ruleTypeRegistry = ruleTypeRegistryMock.create(); const useKibanaMock = useKibana as jest.Mocked; -jest.mock('../../lib/rule_api', () => ({ +jest.mock('../../lib/rule_api/rule_types', () => ({ loadRuleTypes: jest.fn(), +})); +jest.mock('../../lib/rule_api/update', () => ({ updateRule: jest.fn().mockRejectedValue({ body: { message: 'Fail message' } }), +})); +jest.mock('../../lib/rule_api/health', () => ({ alertingFrameworkHealth: jest.fn(() => ({ isSufficientlySecure: true, hasPermanentEncryptionKey: true, @@ -83,7 +87,7 @@ describe('rule_edit', () => { }, }; - const { loadRuleTypes } = jest.requireMock('../../lib/rule_api'); + const { loadRuleTypes } = jest.requireMock('../../lib/rule_api/rule_types'); const ruleTypes = [ { id: 'my-rule-type', diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx index e18d5997e5cf0..9354410ccc9a1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_edit.tsx @@ -38,7 +38,8 @@ import { import { RuleForm } from './rule_form'; import { getRuleActionErrors, getRuleErrors, isValidRule } from './rule_errors'; import { ruleReducer, ConcreteRuleReducer } from './rule_reducer'; -import { updateRule, loadRuleTypes } from '../../lib/rule_api'; +import { updateRule } from '../../lib/rule_api/update'; +import { loadRuleTypes } from '../../lib/rule_api/rule_types'; import { HealthCheck } from '../../components/health_check'; import { HealthContextProvider } from '../../context/health_context'; import { useKibana } from '../../../common/lib/kibana'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge_with_api.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge_with_api.tsx index f64412369af21..d4cd600f98ee5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge_with_api.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge_with_api.tsx @@ -8,11 +8,9 @@ import React, { useCallback, useState } from 'react'; import { useKibana } from '../../../../../common/lib/kibana'; import { SnoozeSchedule } from '../../../../../types'; -import { - loadRule, - snoozeRule as snoozeRuleApi, - unsnoozeRule as unsnoozeRuleApi, -} from '../../../../lib/rule_api'; +import { loadRule } from '../../../../lib/rule_api/get_rule'; +import { unsnoozeRule as unsnoozeRuleApi } from '../../../../lib/rule_api/unsnooze'; +import { snoozeRule as snoozeRuleApi } from '../../../../lib/rule_api/snooze'; import { RulesListNotifyBadge } from './notify_badge'; import { RulesListNotifyBadgePropsWithApi } from './types'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze_modal.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze_modal.tsx index 5d9b13eaded68..a40033e898582 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze_modal.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_snooze_modal.tsx @@ -9,7 +9,8 @@ import React, { useCallback, useMemo } from 'react'; import { EuiModal, EuiModalBody, EuiSpacer } from '@elastic/eui'; import { useKibana } from '../../../../common/lib/kibana'; -import { snoozeRule, unsnoozeRule } from '../../../lib/rule_api'; +import { snoozeRule } from '../../../lib/rule_api/snooze'; +import { unsnoozeRule } from '../../../lib/rule_api/unsnooze'; import { SNOOZE_FAILED_MESSAGE, SNOOZE_SUCCESS_MESSAGE, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx index 67c5f7f7ac200..f70437b33c451 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx @@ -50,21 +50,41 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadActionTypes: jest.fn(), loadAllActions: jest.fn(), })); -jest.mock('../../../lib/rule_api', () => ({ + +jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/rule_types', () => ({ loadRuleTypes: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ loadRuleAggregationsWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/update_api_key', () => ({ updateAPIKey: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate', () => ({ loadRuleTags: jest.fn(), +})); +jest.mock('../../../lib/rule_api/snooze', () => ({ bulkSnoozeRules: jest.fn(), - bulkDeleteRules: jest.fn().mockResolvedValue({ errors: [], total: 10 }), +})); +jest.mock('../../../lib/rule_api/unsnooze', () => ({ bulkUnsnoozeRules: jest.fn(), +})); +jest.mock('../../../lib/rule_api/bulk_delete', () => ({ + bulkDeleteRules: jest.fn().mockResolvedValue({ errors: [], total: 10 }), +})); +jest.mock('../../../lib/rule_api/update_api_key', () => ({ bulkUpdateAPIKey: jest.fn(), +})); +jest.mock('../../../lib/rule_api/health', () => ({ alertingFrameworkHealth: jest.fn(() => ({ isSufficientlySecure: true, hasPermanentEncryptionKey: true, })), })); + jest.mock('../../../lib/rule_api/aggregate_kuery_filter'); jest.mock('../../../lib/rule_api/rules_kuery_filter'); @@ -96,7 +116,10 @@ jest.mock('../../../../common/get_experimental_features', () => ({ const ruleTags = ['a', 'b', 'c', 'd']; -const { loadRuleTypes, bulkUpdateAPIKey, loadRuleTags } = jest.requireMock('../../../lib/rule_api'); +const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); +const { bulkUpdateAPIKey } = jest.requireMock('../../../lib/rule_api/update_api_key'); +const { loadRuleTags } = jest.requireMock('../../../lib/rule_api/aggregate'); + const { loadRuleAggregationsWithKueryFilter } = jest.requireMock( '../../../lib/rule_api/aggregate_kuery_filter' ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index dd3e24bbf13d3..4fc42cea86872 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -56,14 +56,15 @@ import { BulkOperationPopover } from '../../common/components/bulk_operation_pop import { RuleQuickEditButtonsWithApi as RuleQuickEditButtons } from '../../common/components/rule_quick_edit_buttons'; import { CollapsedItemActionsWithApi as CollapsedItemActions } from './collapsed_item_actions'; import { RulesListFiltersBar } from './rules_list_filters_bar'; -import { - snoozeRule, - unsnoozeRule, - bulkUpdateAPIKey, - bulkDisableRules, - bulkEnableRules, - cloneRule, -} from '../../../lib/rule_api'; + +import { snoozeRule } from '../../../lib/rule_api/snooze'; +import { unsnoozeRule } from '../../../lib/rule_api/unsnooze'; +import { bulkUpdateAPIKey } from '../../../lib/rule_api/update_api_key'; +import { bulkDisableRules } from '../../../lib/rule_api/bulk_disable'; +import { bulkEnableRules } from '../../../lib/rule_api/bulk_enable'; +import { bulkDeleteRules } from '../../../lib/rule_api/bulk_delete'; +import { cloneRule } from '../../../lib/rule_api/clone'; + import { hasAllPrivilege, hasExecuteActionsCapability } from '../../../lib/capabilities'; import { DEFAULT_SEARCH_PAGE_SIZE } from '../../../constants'; import { RulesDeleteModalConfirmation } from '../../../components/rules_delete_modal_confirmation'; @@ -81,7 +82,6 @@ import { BulkSnoozeModalWithApi as BulkSnoozeModal } from './bulk_snooze_modal'; import { BulkSnoozeScheduleModalWithApi as BulkSnoozeScheduleModal } from './bulk_snooze_schedule_modal'; import { useBulkEditSelect } from '../../../hooks/use_bulk_edit_select'; import { runRule } from '../../../lib/run_rule'; -import { bulkDeleteRules } from '../../../lib/rule_api'; import { useLoadActionTypesQuery } from '../../../hooks/use_load_action_types_query'; import { useLoadRuleAggregationsQuery } from '../../../hooks/use_load_rule_aggregations_query'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx index 1b4b3cf7970ae..6e9276018f9b9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_delete.test.tsx @@ -31,13 +31,25 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadAllActions: jest.fn(), })); -jest.mock('../../../lib/rule_api', () => ({ +jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/rule_types', () => ({ loadRuleTypes: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ loadRuleAggregationsWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/update_api_key', () => ({ updateAPIKey: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate', () => ({ loadRuleTags: jest.fn(), +})); +jest.mock('../../../lib/rule_api/bulk_delete', () => ({ bulkDeleteRules: jest.fn().mockResolvedValue({ errors: [], total: 10 }), +})); +jest.mock('../../../lib/rule_api/health', () => ({ alertingFrameworkHealth: jest.fn(() => ({ isSufficientlySecure: true, hasPermanentEncryptionKey: true, @@ -74,7 +86,8 @@ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); -const { loadRuleTypes, bulkDeleteRules } = jest.requireMock('../../../lib/rule_api'); +const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); +const { bulkDeleteRules } = jest.requireMock('../../../lib/rule_api/bulk_delete'); const { loadRulesWithKueryFilter } = jest.requireMock('../../../lib/rule_api/rules_kuery_filter'); const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx index 19fe6c68f2646..eb3be548b59fe 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_disable.test.tsx @@ -31,13 +31,25 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadAllActions: jest.fn(), })); -jest.mock('../../../lib/rule_api', () => ({ +jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/rule_types', () => ({ loadRuleTypes: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ loadRuleAggregationsWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/update_api_key', () => ({ updateAPIKey: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate', () => ({ loadRuleTags: jest.fn(), +})); +jest.mock('../../../lib/rule_api/bulk_disable', () => ({ bulkDisableRules: jest.fn().mockResolvedValue({ errors: [], total: 10 }), +})); +jest.mock('../../../lib/rule_api/health', () => ({ alertingFrameworkHealth: jest.fn(() => ({ isSufficientlySecure: true, hasPermanentEncryptionKey: true, @@ -74,7 +86,8 @@ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); -const { loadRuleTypes, bulkDisableRules } = jest.requireMock('../../../lib/rule_api'); +const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); +const { bulkDisableRules } = jest.requireMock('../../../lib/rule_api/bulk_disable'); const { loadRulesWithKueryFilter } = jest.requireMock('../../../lib/rule_api/rules_kuery_filter'); const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx index 48a9995d7a82a..392ebdd8ca48c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_edit.test.tsx @@ -30,15 +30,31 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadAllActions: jest.fn(), })); -jest.mock('../../../lib/rule_api', () => ({ +jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/rule_types', () => ({ loadRuleTypes: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ loadRuleAggregationsWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/update_api_key', () => ({ updateAPIKey: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate', () => ({ loadRuleTags: jest.fn(), +})); +jest.mock('../../../lib/rule_api/snooze', () => ({ bulkSnoozeRules: jest.fn(), +})); +jest.mock('../../../lib/rule_api/unsnooze', () => ({ bulkUnsnoozeRules: jest.fn(), +})); +jest.mock('../../../lib/rule_api/update_api_key', () => ({ bulkUpdateAPIKey: jest.fn(), +})); +jest.mock('../../../lib/rule_api/health', () => ({ alertingFrameworkHealth: jest.fn(() => ({ isSufficientlySecure: true, hasPermanentEncryptionKey: true, @@ -75,8 +91,10 @@ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); -const { loadRuleTypes, bulkSnoozeRules, bulkUnsnoozeRules, bulkUpdateAPIKey } = - jest.requireMock('../../../lib/rule_api'); +const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); +const { bulkSnoozeRules } = jest.requireMock('../../../lib/rule_api/snooze'); +const { bulkUnsnoozeRules } = jest.requireMock('../../../lib/rule_api/unsnooze'); +const { bulkUpdateAPIKey } = jest.requireMock('../../../lib/rule_api/update_api_key'); const { loadRulesWithKueryFilter } = jest.requireMock('../../../lib/rule_api/rules_kuery_filter'); const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx index 688e0ae50ec46..0cc662a28a69e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list_bulk_enable.test.tsx @@ -31,13 +31,25 @@ jest.mock('../../../lib/action_connector_api', () => ({ loadAllActions: jest.fn(), })); -jest.mock('../../../lib/rule_api', () => ({ +jest.mock('../../../lib/rule_api/rules_kuery_filter', () => ({ loadRulesWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/rule_types', () => ({ loadRuleTypes: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate_kuery_filter', () => ({ loadRuleAggregationsWithKueryFilter: jest.fn(), +})); +jest.mock('../../../lib/rule_api/update_api_key', () => ({ updateAPIKey: jest.fn(), +})); +jest.mock('../../../lib/rule_api/aggregate', () => ({ loadRuleTags: jest.fn(), +})); +jest.mock('../../../lib/rule_api/bulk_enable', () => ({ bulkEnableRules: jest.fn().mockResolvedValue({ errors: [], total: 10 }), +})); +jest.mock('../../../lib/rule_api/health', () => ({ alertingFrameworkHealth: jest.fn(() => ({ isSufficientlySecure: true, hasPermanentEncryptionKey: true, @@ -74,7 +86,8 @@ jest.mock('../../../../common/get_experimental_features', () => ({ getIsExperimentalFeatureEnabled: jest.fn(), })); -const { loadRuleTypes, bulkEnableRules } = jest.requireMock('../../../lib/rule_api'); +const { loadRuleTypes } = jest.requireMock('../../../lib/rule_api/rule_types'); +const { bulkEnableRules } = jest.requireMock('../../../lib/rule_api/bulk_enable'); const { loadRulesWithKueryFilter } = jest.requireMock('../../../lib/rule_api/rules_kuery_filter'); const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); diff --git a/x-pack/plugins/triggers_actions_ui/public/index.ts b/x-pack/plugins/triggers_actions_ui/public/index.ts index 6763f9b1921d7..43bc6535df87a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/index.ts @@ -130,19 +130,10 @@ export type { export { Plugin } from './plugin'; // TODO remove this import when we expose the Rules tables as a component -export { loadRules } from './application/lib/rule_api/rules'; -export { loadExecutionLogAggregations } from './application/lib/rule_api/load_execution_log_aggregations'; -export { loadActionErrorLog } from './application/lib/rule_api/load_action_error_log'; -export { loadRuleTypes } from './application/lib/rule_api/rule_types'; export { loadRuleSummary } from './application/lib/rule_api/rule_summary'; -export { muteRule } from './application/lib/rule_api/mute'; export { bulkDeleteRules } from './application/lib/rule_api/bulk_delete'; -export { unmuteRule } from './application/lib/rule_api/unmute'; -export { snoozeRule } from './application/lib/rule_api/snooze'; -export { unsnoozeRule } from './application/lib/rule_api/unsnooze'; -export { loadRuleAggregations, loadRuleTags } from './application/lib/rule_api/aggregate'; +export { loadRuleAggregations } from './application/lib/rule_api/aggregate'; export { loadRule } from './application/lib/rule_api/get_rule'; -export { loadAllActions } from './application/lib/action_connector_api'; export { suspendedComponentWithProps } from './application/lib/suspended_component_with_props'; export { loadActionTypes } from './application/lib/action_connector_api/connector_types'; export { TIME_UNITS } from './application/constants'; From 2bfbddbd1dde19492965ec8f496fda3f4f66e1da Mon Sep 17 00:00:00 2001 From: christineweng <18648970+christineweng@users.noreply.github.com> Date: Mon, 13 Feb 2023 16:25:24 -0600 Subject: [PATCH 147/203] [Security Solution]Alert page chart selection default to summary (#151073) ## Summary This PR addresses a visual bug mentioned in https://github.com/elastic/kibana/issues/151044. Before implementing the `Summary` option, the charts defaults to `Trend`, this PR changes the default to `Summary` when `isAlertsPageCharts` is enabled. **Before** ![image](https://user-images.githubusercontent.com/18648970/218564106-fba96942-cb11-4f57-97ba-a06afccd2d15.png) **After** ![image](https://user-images.githubusercontent.com/18648970/218564231-3103f39f-7d33-43f9-b435-92470491b7ef.png) ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### Note for desk testing Desk testing can be tricky because the selection is stored in local storage. The fastest way I found to test is to use a browser you don't use often (like Safari), clear all browsing data, cache etc., and then open kibana. --- .../alerts_local_storage/index.test.tsx | 27 ++++++++++++++++++- .../alerts_local_storage/index.tsx | 6 +++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.test.tsx index 1787955fb1b52..8145fcf698704 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.test.tsx @@ -10,13 +10,18 @@ import React from 'react'; import { useAlertsLocalStorage } from '.'; import { TestProviders } from '../../../../../common/mock'; +import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; + +const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; +jest.mock('../../../../../common/hooks/use_experimental_features'); describe('useAlertsLocalStorage', () => { const wrapper = ({ children }: { children: React.ReactNode }) => ( {children} ); - test('it returns the expected defaults', () => { + test('it returns the expected defaults when isAlertsPageCharts is disabled', () => { + mockUseIsExperimentalFeatureEnabled.mockReturnValue(false); const { result } = renderHook(() => useAlertsLocalStorage(), { wrapper }); const defaults = Object.fromEntries( @@ -34,4 +39,24 @@ describe('useAlertsLocalStorage', () => { trendChartStackBy: 'kibana.alert.rule.name', }); }); + + test('it returns the expected defaults when isAlertsPageCharts is enaabled', () => { + mockUseIsExperimentalFeatureEnabled.mockReturnValue(true); + const { result } = renderHook(() => useAlertsLocalStorage(), { wrapper }); + + const defaults = Object.fromEntries( + Object.entries(result.current).filter((x) => typeof x[1] !== 'function') + ); + + expect(defaults).toEqual({ + alertViewSelection: 'charts', // default to the summary + countTableStackBy0: 'kibana.alert.rule.name', + countTableStackBy1: 'host.name', + groupBySelection: 'host.name', + isTreemapPanelExpanded: true, + riskChartStackBy0: 'kibana.alert.rule.name', + riskChartStackBy1: 'host.name', + trendChartStackBy: 'kibana.alert.rule.name', + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.tsx index 4af424c0ead8b..468edd14575c2 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/chart_panels/alerts_local_storage/index.tsx @@ -30,12 +30,14 @@ import { } from '../../../../components/alerts_kpis/common/config'; import type { AlertsSettings } from './types'; import type { AlertViewSelection } from '../chart_select/helpers'; -import { TREND_ID } from '../chart_select/helpers'; +import { CHARTS_ID, TREND_ID } from '../chart_select/helpers'; import type { GroupBySelection } from '../../../../components/alerts_kpis/alerts_progress_bar_panel/types'; +import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; export const useAlertsLocalStorage = (): AlertsSettings => { + const isAlertsPageChartsEnabled = useIsExperimentalFeatureEnabled('alertsPageChartsEnabled'); const [alertViewSelection, setAlertViewSelection] = useLocalStorage({ - defaultValue: TREND_ID, + defaultValue: isAlertsPageChartsEnabled ? CHARTS_ID : TREND_ID, key: getSettingKey({ category: VIEW_CATEGORY, page: ALERTS_PAGE, From 9d7e1095365483ad9bc083829f3f291c478e7cf6 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 13 Feb 2023 15:49:52 -0700 Subject: [PATCH 148/203] [maps] include vector tile layers in geoShapeAggLayersCount telemetry (#151072) While investigating https://github.com/elastic/kibana/issues/151064, I found a problem with IndexPatternStatsCollector where geo_shape aggregation usage with vector tile layers are not counted. Steps to view problem: * Download [world countries geojson](https://vector.maps.elastic.co/files/world_countries_v7.geo.json?elastic_tile_service_tos=agree&my_app_name=ems-landing-page&my_app_version=8.6.0&license=643c1faf-80fc-4ab0-9323-4d9bd11f4bbc) * use file upload to upload world countries into your Elastic stack * add a new cluster layer to your map. * Select world countries index * Select **Hexagons** * Click **Add layer** * Save map * Open borwser dev tools and switch to network tab * Open Kibana dev tools and run ``` POST kbn:api/telemetry/v2/clusters/_stats { "unencrypted": true } ``` * Copy response for `_stats` request. Search for `geoShapeAggLayersCount`. Notice how the value is zero but it should be one since you have one map using geo shape aggregation Screen Shot 2023-02-13 at 1 14 34 PM PR resolves the problem by removing layer type guard. The guard is error prone and easy to not update with new layer types. The guard does not provide any value, since the logic is really concerned with source types and the source type guards provide the correct protections. Steps to test: Follow steps above and verify `geoShapeAggLayersCount` is one --- .../index_pattern_stats_collector.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.ts b/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.ts index dcbc9c884275d..2b8047cdaf41f 100644 --- a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.ts +++ b/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.ts @@ -9,7 +9,7 @@ import type { SavedObject } from '@kbn/core/server'; import { asyncForEach } from '@kbn/std'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { DataViewsService } from '@kbn/data-views-plugin/common'; -import { LAYER_TYPE, SCALING_TYPES, SOURCE_TYPES } from '../../../common/constants'; +import { SCALING_TYPES, SOURCE_TYPES } from '../../../common/constants'; import { injectReferences } from '../../../common/migrations/references'; import { ESGeoGridSourceDescriptor, @@ -107,14 +107,6 @@ export class IndexPatternStatsCollector { return false; } - if ( - layer.type !== LAYER_TYPE.GEOJSON_VECTOR && - layer.type !== LAYER_TYPE.BLENDED_VECTOR && - layer.type !== LAYER_TYPE.HEATMAP - ) { - return false; - } - const sourceDescriptor = layer.sourceDescriptor; if (sourceDescriptor.type === SOURCE_TYPES.ES_GEO_GRID) { return await this._isFieldGeoShape( From 5e3056f4a0db5b28d87bcf4446a60539383db032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20Gr=C3=A9au?= Date: Mon, 13 Feb 2023 17:50:05 -0500 Subject: [PATCH 149/203] Set commit msg when updating gitops repo to publish new image (#151083) ## Summary This update sets the commit message to push to the gitops repository when a new Kibana image is published. Also to align with the other services the `IMAGE_TAG` is prefixed by `git-` and uses a 12 characters short commit value. ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .buildkite/scripts/steps/artifacts/docker_image.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.buildkite/scripts/steps/artifacts/docker_image.sh b/.buildkite/scripts/steps/artifacts/docker_image.sh index badc8f4ea4e9d..f263812932a2d 100755 --- a/.buildkite/scripts/steps/artifacts/docker_image.sh +++ b/.buildkite/scripts/steps/artifacts/docker_image.sh @@ -6,8 +6,8 @@ set -euo pipefail source .buildkite/scripts/steps/artifacts/env.sh -GIT_ABBREV_COMMIT=${BUILDKITE_COMMIT:0:7} -KIBANA_IMAGE="docker.elastic.co/kibana-ci/kibana:$GIT_ABBREV_COMMIT" +GIT_ABBREV_COMMIT=${BUILDKITE_COMMIT:0:12} +KIBANA_IMAGE="docker.elastic.co/kibana-ci/kibana:git-$GIT_ABBREV_COMMIT" echo "--- Verify manifest does not already exist" echo "$KIBANA_DOCKER_PASSWORD" | docker login -u "$KIBANA_DOCKER_USERNAME" --password-stdin docker.elastic.co @@ -82,16 +82,17 @@ if [[ "$BUILDKITE_BRANCH" == "$KIBANA_BASE_BRANCH" ]]; then cat << EOF | buildkite-agent pipeline upload steps: - trigger: k8s-gitops-update-image-tag - label: ":argo: Update image tag for deployment-api" + label: ":argo: Update image tag for Kibana" branches: main build: env: MODE: sed TARGET_FILE: kibana-controller.yaml - IMAGE_TAG: "$GIT_ABBREV_COMMIT" + IMAGE_TAG: "git-$GIT_ABBREV_COMMIT" SERVICE: kibana-controller NAMESPACE: kibana-ci IMAGE_NAME: kibana + COMMIT_MESSAGE: "gitops: update kibana tag to elastic/kibana@$BUILDKITE_COMMIT" EOF else From e8c18a121e8e5fda9fbea92ddf85937cbe816fde Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Mon, 13 Feb 2023 18:31:02 -0500 Subject: [PATCH 150/203] [Response Ops][Alerting] Update alerts-as-data ILM policy name to be consistent between framework & rule registry (#150334) Resolves https://github.com/elastic/kibana/issues/150331 ## Summary In a previous [PR](https://github.com/elastic/kibana/pull/145581) we started installing an ILM policy for framework alerts as data when the `xpack.alerting.enableFrameworkAlerts` config flag is set to true. In that PR we used a different name than what is used by the rule registry even though the policy bodies were the same. In this PR, we are consolidating the naming of the two ILM policies so that we are only ever installing 1 policy. The `xpack.alerting.enableFrameworkAlerts` config is used to determine which plugin is responsible for installing the policy. When set to true, the alerting plugin installs the policy. When set the false, the rule registry installs the policy. This is an incremental step toward the alerting framework absorbing all of the resource installation functionality of the rule registry ## To Verify A few things to verify: 1. Verify that the alerting plugin installs the policy when `xpack.alerting.enableFrameworkAlerts=true` * Set `xpack.alerting.enableFrameworkAlerts: true` in your Kibana config * Start a fresh ES and Kibana instance * Verify that an ILM policy with name `.alerts-ilm-policy` is installed * Create a metric threshold rule that creates an alert * Verify that there is an index template called `.alerts-observability.metrics.alerts-default-index-template` that uses the `.alerts-ilm-policy` policy 2. Verify that the rule registry installs the policy when `xpack.alerting.enableFrameworkAlerts=false` * Set `xpack.alerting.enableFrameworkAlerts: false` in your Kibana config * Start a fresh ES and Kibana instance * Verify that an ILM policy with name `.alerts-ilm-policy` is installed * Create a metric threshold rule that creates an alert * Verify that there is an index template called `.alerts-observability.metrics.alerts-default-index-template` that uses the `.alerts-ilm-policy` policy 3. Verify that we can switch between configurations * Set `xpack.alerting.enableFrameworkAlerts: false` in your Kibana config * Start a fresh ES and Kibana instance * Verify that an ILM policy with name `.alerts-ilm-policy` is installed * Create a metric threshold rule that creates an alert * Verify that there is an index template called `.alerts-observability.metrics.alerts-default-index-template` that uses the `.alerts-ilm-policy` policy * Change `xpack.alerting.enableFrameworkAlerts: true` * Restart Kibana * Verify there are no errors, and the rule can still write alerts --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../alerts_service/alerts_service.test.ts | 8 ++-- .../server/alerts_service/alerts_service.ts | 17 +++++--- .../default_lifecycle_policy.ts | 4 +- x-pack/plugins/alerting/server/index.ts | 4 ++ x-pack/plugins/alerting/server/mocks.ts | 1 + x-pack/plugins/alerting/server/plugin.test.ts | 6 ++- x-pack/plugins/alerting/server/plugin.ts | 2 + x-pack/plugins/rule_registry/common/assets.ts | 1 - .../default_lifecycle_policy.ts | 24 ------------ x-pack/plugins/rule_registry/server/plugin.ts | 7 +++- .../resource_installer.test.ts | 39 ++++++++++++++++++- .../resource_installer.ts | 28 +++++++------ .../rule_data_plugin_service.test.ts | 4 ++ .../rule_data_plugin_service.ts | 2 + .../tests/alerting/group4/alerts_as_data.ts | 6 +-- .../tests/trial/get_summarized_alerts.ts | 1 + .../tests/trial/lifecycle_executor.ts | 1 + 17 files changed, 100 insertions(+), 55 deletions(-) delete mode 100644 x-pack/plugins/rule_registry/common/assets/lifecycle_policies/default_lifecycle_policy.ts diff --git a/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts b/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts index ba3623526591f..82716f935c6b3 100644 --- a/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts +++ b/x-pack/plugins/alerting/server/alerts_service/alerts_service.test.ts @@ -72,7 +72,7 @@ const IlmPutBody = { }, }, }, - name: 'alerts-default-ilm-policy', + name: '.alerts-ilm-policy', }; const getIndexTemplatePutBody = (context?: string) => ({ @@ -88,7 +88,7 @@ const getIndexTemplatePutBody = (context?: string) => ({ auto_expand_replicas: '0-1', hidden: true, 'index.lifecycle': { - name: 'alerts-default-ilm-policy', + name: '.alerts-ilm-policy', rollover_alias: `.alerts-${context ? context : 'test'}-default`, }, 'index.mapping.total_fields.limit': 2500, @@ -165,7 +165,7 @@ describe('Alerts Service', () => { expect(alertsService.isInitialized()).toEqual(false); expect(logger.error).toHaveBeenCalledWith( - `Error installing ILM policy alerts-default-ilm-policy - fail` + `Error installing ILM policy .alerts-ilm-policy - fail` ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); @@ -342,7 +342,7 @@ describe('Alerts Service', () => { auto_expand_replicas: '0-1', hidden: true, 'index.lifecycle': { - name: 'alerts-default-ilm-policy', + name: '.alerts-ilm-policy', rollover_alias: `.alerts-empty-default`, }, 'index.mapping.total_fields.limit': 2500, diff --git a/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts b/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts index 0742be50c4fa4..08643caf862f5 100644 --- a/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts +++ b/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts @@ -15,7 +15,10 @@ import { Logger, ElasticsearchClient } from '@kbn/core/server'; import { firstValueFrom, Observable } from 'rxjs'; import { FieldMap } from '../../common/alert_schema/field_maps/types'; import { alertFieldMap } from '../../common/alert_schema'; -import { ILM_POLICY_NAME, DEFAULT_ILM_POLICY } from './default_lifecycle_policy'; +import { + DEFAULT_ALERTS_ILM_POLICY_NAME, + DEFAULT_ALERTS_ILM_POLICY, +} from './default_lifecycle_policy'; import { getComponentTemplate, getComponentTemplateName, @@ -178,19 +181,21 @@ export class AlertsService implements IAlertsService { * Creates ILM policy if it doesn't already exist, updates it if it does */ private async createOrUpdateIlmPolicy(esClient: ElasticsearchClient) { - this.options.logger.info(`Installing ILM policy ${ILM_POLICY_NAME}`); + this.options.logger.info(`Installing ILM policy ${DEFAULT_ALERTS_ILM_POLICY_NAME}`); try { await retryTransientEsErrors( () => esClient.ilm.putLifecycle({ - name: ILM_POLICY_NAME, - body: DEFAULT_ILM_POLICY, + name: DEFAULT_ALERTS_ILM_POLICY_NAME, + body: DEFAULT_ALERTS_ILM_POLICY, }), { logger: this.options.logger } ); } catch (err) { - this.options.logger.error(`Error installing ILM policy ${ILM_POLICY_NAME} - ${err.message}`); + this.options.logger.error( + `Error installing ILM policy ${DEFAULT_ALERTS_ILM_POLICY_NAME} - ${err.message}` + ); throw err; } } @@ -236,7 +241,7 @@ export class AlertsService implements IAlertsService { auto_expand_replicas: '0-1', hidden: true, 'index.lifecycle': { - name: ILM_POLICY_NAME, + name: DEFAULT_ALERTS_ILM_POLICY_NAME, rollover_alias: indexPatterns.alias, }, 'index.mapping.total_fields.limit': TOTAL_FIELDS_LIMIT, diff --git a/x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts b/x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts index f5d11c6214ee6..5e8c40cf6f6a8 100644 --- a/x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts +++ b/x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts @@ -14,8 +14,8 @@ * This should be used by all alerts-as-data indices */ -export const ILM_POLICY_NAME = 'alerts-default-ilm-policy'; -export const DEFAULT_ILM_POLICY = { +export const DEFAULT_ALERTS_ILM_POLICY_NAME = '.alerts-ilm-policy'; +export const DEFAULT_ALERTS_ILM_POLICY = { policy: { _meta: { managed: true, diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts index 8d42aa47091f2..a13b06596f557 100644 --- a/x-pack/plugins/alerting/server/index.ts +++ b/x-pack/plugins/alerting/server/index.ts @@ -53,6 +53,10 @@ export { WriteOperations, AlertingAuthorizationEntity, } from './authorization'; +export { + DEFAULT_ALERTS_ILM_POLICY, + DEFAULT_ALERTS_ILM_POLICY_NAME, +} from './alerts_service/default_lifecycle_policy'; export const plugin = (initContext: PluginInitializerContext) => new AlertingPlugin(initContext); diff --git a/x-pack/plugins/alerting/server/mocks.ts b/x-pack/plugins/alerting/server/mocks.ts index d997b709c0960..787ab3e9c856f 100644 --- a/x-pack/plugins/alerting/server/mocks.ts +++ b/x-pack/plugins/alerting/server/mocks.ts @@ -30,6 +30,7 @@ const createSetupMock = () => { registerType: jest.fn(), getSecurityHealth: jest.fn(), getConfig: jest.fn(), + getFrameworkAlertsEnabled: jest.fn(), }; return mock; }; diff --git a/x-pack/plugins/alerting/server/plugin.test.ts b/x-pack/plugins/alerting/server/plugin.test.ts index 4e48c0db01ae6..f0dd5ce64315f 100644 --- a/x-pack/plugins/alerting/server/plugin.test.ts +++ b/x-pack/plugins/alerting/server/plugin.test.ts @@ -132,10 +132,12 @@ describe('Alerting Plugin', () => { plugin = new AlertingPlugin(context); // need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices() - await plugin.setup(setupMocks, mockPlugins); + const setupContract = await plugin.setup(setupMocks, mockPlugins); expect(AlertsService).toHaveBeenCalled(); expect(mockAlertService.initialize).toHaveBeenCalled(); + + expect(setupContract.getFrameworkAlertsEnabled()).toEqual(true); }); it(`exposes configured minimumScheduleInterval()`, async () => { @@ -150,6 +152,8 @@ describe('Alerting Plugin', () => { isUsingSecurity: false, minimumScheduleInterval: { value: '1m', enforce: false }, }); + + expect(setupContract.getFrameworkAlertsEnabled()).toEqual(false); }); describe('registerType()', () => { diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 6070b5cee56fb..414d4f4e01b91 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -126,6 +126,7 @@ export interface PluginSetupContract { ): void; getSecurityHealth: () => Promise; getConfig: () => AlertingRulesConfig; + getFrameworkAlertsEnabled: () => boolean; } export interface PluginStartContract { @@ -385,6 +386,7 @@ export class AlertingPlugin { isUsingSecurity: this.licenseState ? !!this.licenseState.getIsSecurityEnabled() : false, }; }, + getFrameworkAlertsEnabled: () => this.config.enableFrameworkAlerts, }; } diff --git a/x-pack/plugins/rule_registry/common/assets.ts b/x-pack/plugins/rule_registry/common/assets.ts index 1a5b14c605ea5..a1df09df18a8f 100644 --- a/x-pack/plugins/rule_registry/common/assets.ts +++ b/x-pack/plugins/rule_registry/common/assets.ts @@ -7,4 +7,3 @@ export const TECHNICAL_COMPONENT_TEMPLATE_NAME = `technical-mappings`; export const ECS_COMPONENT_TEMPLATE_NAME = `ecs-mappings`; -export const DEFAULT_ILM_POLICY_ID = 'ilm-policy'; diff --git a/x-pack/plugins/rule_registry/common/assets/lifecycle_policies/default_lifecycle_policy.ts b/x-pack/plugins/rule_registry/common/assets/lifecycle_policies/default_lifecycle_policy.ts deleted file mode 100644 index 449a425ad3aa6..0000000000000 --- a/x-pack/plugins/rule_registry/common/assets/lifecycle_policies/default_lifecycle_policy.ts +++ /dev/null @@ -1,24 +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 defaultLifecyclePolicy = { - policy: { - _meta: { - managed: true, - }, - phases: { - hot: { - actions: { - rollover: { - max_age: '30d', - max_primary_shard_size: '50gb', - }, - }, - }, - }, - }, -}; diff --git a/x-pack/plugins/rule_registry/server/plugin.ts b/x-pack/plugins/rule_registry/server/plugin.ts index 68b2df1224065..8b5c754e5b908 100644 --- a/x-pack/plugins/rule_registry/server/plugin.ts +++ b/x-pack/plugins/rule_registry/server/plugin.ts @@ -16,7 +16,10 @@ import type { IContextProvider, } from '@kbn/core/server'; -import type { PluginStartContract as AlertingStart } from '@kbn/alerting-plugin/server'; +import type { + PluginSetupContract as AlertingSetup, + PluginStartContract as AlertingStart, +} from '@kbn/alerting-plugin/server'; import type { SecurityPluginSetup } from '@kbn/security-plugin/server'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import type { @@ -36,6 +39,7 @@ import { ruleRegistrySearchStrategyProvider, RULE_SEARCH_STRATEGY_NAME } from '. export interface RuleRegistryPluginSetupDependencies { security?: SecurityPluginSetup; data: DataPluginSetup; + alerting: AlertingSetup; } export interface RuleRegistryPluginStartDependencies { @@ -106,6 +110,7 @@ export class RuleRegistryPlugin const deps = await startDependencies; return deps.core.elasticsearch.client.asInternalUser; }, + areFrameworkAlertsEnabled: plugins.alerting.getFrameworkAlertsEnabled(), pluginStop$: this.pluginStop$, }); diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.test.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.test.ts index d73b1898671bb..b63fb2aae83d0 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.test.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.test.ts @@ -14,7 +14,6 @@ import { Dataset } from './index_options'; import { IndexInfo } from './index_info'; import { elasticsearchServiceMock, ElasticsearchClientMock } from '@kbn/core/server/mocks'; import { - DEFAULT_ILM_POLICY_ID, ECS_COMPONENT_TEMPLATE_NAME, TECHNICAL_COMPONENT_TEMPLATE_NAME, } from '../../common/assets'; @@ -41,6 +40,7 @@ describe('resourceInstaller', () => { disabledRegistrationContexts: [], getResourceName: jest.fn(), getClusterClient, + areFrameworkAlertsEnabled: false, pluginStop$, }); installer.installCommonResources(); @@ -57,6 +57,7 @@ describe('resourceInstaller', () => { disabledRegistrationContexts: [], getResourceName: jest.fn(), getClusterClient, + areFrameworkAlertsEnabled: false, pluginStop$, }); const indexOptions = { @@ -83,7 +84,6 @@ describe('resourceInstaller', () => { const getClusterClient = jest.fn(() => Promise.resolve(mockClusterClient)); const getResourceNameMock = jest .fn() - .mockReturnValueOnce(DEFAULT_ILM_POLICY_ID) .mockReturnValueOnce(TECHNICAL_COMPONENT_TEMPLATE_NAME) .mockReturnValueOnce(ECS_COMPONENT_TEMPLATE_NAME); const installer = new ResourceInstaller({ @@ -92,6 +92,7 @@ describe('resourceInstaller', () => { disabledRegistrationContexts: [], getResourceName: getResourceNameMock, getClusterClient, + areFrameworkAlertsEnabled: false, pluginStop$, }); @@ -108,6 +109,38 @@ describe('resourceInstaller', () => { expect.objectContaining({ name: ECS_COMPONENT_TEMPLATE_NAME }) ); }); + + it('should install common resources when framework alerts are enabled', async () => { + const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient(); + const getClusterClient = jest.fn(() => Promise.resolve(mockClusterClient)); + const getResourceNameMock = jest + .fn() + .mockReturnValueOnce(TECHNICAL_COMPONENT_TEMPLATE_NAME) + .mockReturnValueOnce(ECS_COMPONENT_TEMPLATE_NAME); + const installer = new ResourceInstaller({ + logger: loggerMock.create(), + isWriteEnabled: true, + disabledRegistrationContexts: [], + getResourceName: getResourceNameMock, + getClusterClient, + areFrameworkAlertsEnabled: true, + pluginStop$, + }); + + await installer.installCommonResources(); + + // ILM policy should be handled by framework + expect(mockClusterClient.ilm.putLifecycle).not.toHaveBeenCalled(); + expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ name: TECHNICAL_COMPONENT_TEMPLATE_NAME }) + ); + expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ name: ECS_COMPONENT_TEMPLATE_NAME }) + ); + }); it('should install index level resources', async () => { const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient(); const getClusterClient = jest.fn(() => Promise.resolve(mockClusterClient)); @@ -117,6 +150,7 @@ describe('resourceInstaller', () => { disabledRegistrationContexts: [], getResourceName: jest.fn(), getClusterClient, + areFrameworkAlertsEnabled: false, pluginStop$, }); @@ -188,6 +222,7 @@ describe('resourceInstaller', () => { disabledRegistrationContexts: [], getResourceName: jest.fn(), getClusterClient: async () => mockClusterClient, + areFrameworkAlertsEnabled: false, pluginStop$, }; const indexOptions = { 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 30b867d114446..6af288e57a4a0 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 @@ -13,13 +13,15 @@ import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { - DEFAULT_ILM_POLICY_ID, + DEFAULT_ALERTS_ILM_POLICY, + DEFAULT_ALERTS_ILM_POLICY_NAME, +} from '@kbn/alerting-plugin/server'; +import { ECS_COMPONENT_TEMPLATE_NAME, TECHNICAL_COMPONENT_TEMPLATE_NAME, } from '../../common/assets'; import { technicalComponentTemplate } from '../../common/assets/component_templates/technical_component_template'; import { ecsComponentTemplate } from '../../common/assets/component_templates/ecs_component_template'; -import { defaultLifecyclePolicy } from '../../common/assets/lifecycle_policies/default_lifecycle_policy'; import type { IndexInfo } from './index_info'; @@ -31,6 +33,7 @@ interface ConstructorOptions { logger: Logger; isWriteEnabled: boolean; disabledRegistrationContexts: string[]; + areFrameworkAlertsEnabled: boolean; pluginStop$: Observable; } @@ -95,16 +98,21 @@ export class ResourceInstaller { */ public async installCommonResources(): Promise { await this.installWithTimeout('common resources shared between all indices', async () => { - const { getResourceName, logger } = this.options; + const { getResourceName, logger, areFrameworkAlertsEnabled } = this.options; try { // We can install them in parallel await Promise.all([ - this.createOrUpdateLifecyclePolicy({ - name: getResourceName(DEFAULT_ILM_POLICY_ID), - body: defaultLifecyclePolicy, - }), - + // Install ILM policy only if framework alerts are not enabled + // If framework alerts are enabled, the alerting framework will install this ILM policy + ...(areFrameworkAlertsEnabled + ? [] + : [ + this.createOrUpdateLifecyclePolicy({ + name: DEFAULT_ALERTS_ILM_POLICY_NAME, + body: DEFAULT_ALERTS_ILM_POLICY, + }), + ]), this.createOrUpdateComponentTemplate({ name: getResourceName(TECHNICAL_COMPONENT_TEMPLATE_NAME), body: technicalComponentTemplate, @@ -326,9 +334,7 @@ export class ResourceInstaller { const ownComponentNames = componentTemplates.map((template) => indexInfo.getComponentTemplateName(template.name) ); - const ilmPolicyName = ilmPolicy - ? indexInfo.getIlmPolicyName() - : getResourceName(DEFAULT_ILM_POLICY_ID); + const ilmPolicyName = ilmPolicy ? indexInfo.getIlmPolicyName() : DEFAULT_ALERTS_ILM_POLICY_NAME; const indexMetadata: estypes.Metadata = { ...indexTemplate._meta, diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.test.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.test.ts index 997137877bc9b..1022ea038bc3e 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.test.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.test.ts @@ -43,6 +43,7 @@ describe('ruleDataPluginService', () => { isWriteEnabled: true, disabledRegistrationContexts: ['observability.logs'], isWriterCacheEnabled: true, + areFrameworkAlertsEnabled: false, pluginStop$, }); expect(ruleDataService.isRegistrationContextDisabled('observability.logs')).toBe(true); @@ -59,6 +60,7 @@ describe('ruleDataPluginService', () => { isWriteEnabled: true, disabledRegistrationContexts: ['observability.logs'], isWriterCacheEnabled: true, + areFrameworkAlertsEnabled: false, pluginStop$, }); expect(ruleDataService.isRegistrationContextDisabled('observability.apm')).toBe(false); @@ -77,6 +79,7 @@ describe('ruleDataPluginService', () => { isWriteEnabled: true, disabledRegistrationContexts: ['observability.logs'], isWriterCacheEnabled: true, + areFrameworkAlertsEnabled: false, pluginStop$, }); @@ -96,6 +99,7 @@ describe('ruleDataPluginService', () => { isWriteEnabled: true, disabledRegistrationContexts: ['observability.logs'], isWriterCacheEnabled: true, + areFrameworkAlertsEnabled: false, pluginStop$, }); const indexOptions = { diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts index 459e4bacf9a66..b3f54a1d3794d 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts @@ -91,6 +91,7 @@ interface ConstructorOptions { isWriteEnabled: boolean; isWriterCacheEnabled: boolean; disabledRegistrationContexts: string[]; + areFrameworkAlertsEnabled: boolean; pluginStop$: Observable; } @@ -112,6 +113,7 @@ export class RuleDataService implements IRuleDataService { logger: options.logger, disabledRegistrationContexts: options.disabledRegistrationContexts, isWriteEnabled: options.isWriteEnabled, + areFrameworkAlertsEnabled: options.areFrameworkAlertsEnabled, pluginStop$: options.pluginStop$, }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data.ts index 49ec03fc6d8d8..3ac2fdb93add8 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/alerts_as_data.ts @@ -17,7 +17,7 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex describe('alerts as data', () => { it('should install common alerts as data resources on startup', async () => { - const ilmPolicyName = 'alerts-default-ilm-policy'; + const ilmPolicyName = '.alerts-ilm-policy'; const componentTemplateName = 'alerts-common-component-template'; const commonIlmPolicy = await es.ilm.getLifecycle({ @@ -123,7 +123,7 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex expect(contextIndexTemplate.index_template.template!.settings).to.eql({ index: { lifecycle: { - name: 'alerts-default-ilm-policy', + name: '.alerts-ilm-policy', rollover_alias: '.alerts-test.always-firing-default', }, mapping: { @@ -155,7 +155,7 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex }); expect(contextIndex[indexName].settings?.index?.lifecycle).to.eql({ - name: 'alerts-default-ilm-policy', + name: '.alerts-ilm-policy', rollover_alias: '.alerts-test.always-firing-default', }); diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/get_summarized_alerts.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/get_summarized_alerts.ts index b62d744503fc6..02765aa8c2a77 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/get_summarized_alerts.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/get_summarized_alerts.ts @@ -80,6 +80,7 @@ export default function createGetSummarizedAlertsTest({ getService }: FtrProvide isWriteEnabled: true, isWriterCacheEnabled: false, disabledRegistrationContexts: [] as string[], + areFrameworkAlertsEnabled: false, pluginStop$, }); diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts index 2fbba4478e925..dc5752417bfb4 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/lifecycle_executor.ts @@ -74,6 +74,7 @@ export default function createLifecycleExecutorApiTest({ getService }: FtrProvid isWriteEnabled: true, isWriterCacheEnabled: false, disabledRegistrationContexts: [] as string[], + areFrameworkAlertsEnabled: false, pluginStop$, }); From e8994b831ef773b133f9d6f34c0726e1840fe315 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 17:58:54 -0600 Subject: [PATCH 151/203] Update dependency @babel/parser to ^7.20.15 (main) (#150825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [@babel/parser](https://babel.dev/docs/en/next/babel-parser) ([source](https://togithub.com/babel/babel)) | [`^7.20.13` -> `^7.20.15`](https://renovatebot.com/diffs/npm/@babel%2fparser/7.20.13/7.20.15) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.20.15/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.20.15/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.20.15/compatibility-slim/7.20.13)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.20.15/confidence-slim/7.20.13)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
babel/babel ### [`v7.20.15`](https://togithub.com/babel/babel/releases/tag/v7.20.15) [Compare Source](https://togithub.com/babel/babel/compare/v7.20.13...v7.20.15) #### v7.20.15 (2023-02-02) ##### :eyeglasses: Spec Compliance - `babel-parser` - [#​15391](https://togithub.com/babel/babel/pull/15391) Disallow await as bound name in using declaration ([@​JLHwung](https://togithub.com/JLHwung)) - `babel-generator`, `babel-parser`, `babel-plugin-proposal-export-namespace-from` - [#​15385](https://togithub.com/babel/babel/pull/15385) Disallows specifiers after export \* as ns ([@​JLHwung](https://togithub.com/JLHwung)) ##### :bug: Bug Fix - `babel-plugin-transform-block-scoping` - [#​15398](https://togithub.com/babel/babel/pull/15398) fix: Loop was converted wrong ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-parser` - [#​15377](https://togithub.com/babel/babel/pull/15377) fix: `new (foo?.bar)()` incorrectly throws exception `OptionalChainingNoNew` ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) ##### Committers: 2 - Huáng Jùnliàng ([@​JLHwung](https://togithub.com/JLHwung)) - [@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)
--- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/elastic/kibana). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jonathan Budzenski --- package.json | 2 +- yarn.lock | 17 +++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 4f4ce4cdf4c63..a3e5a3b5f6e33 100644 --- a/package.json +++ b/package.json @@ -948,7 +948,7 @@ "@babel/eslint-plugin": "^7.19.1", "@babel/generator": "^7.20.14", "@babel/helper-plugin-utils": "^7.20.2", - "@babel/parser": "^7.20.13", + "@babel/parser": "^7.20.15", "@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", diff --git a/yarn.lock b/yarn.lock index 9be0124443384..405c3ad9bf181 100644 --- a/yarn.lock +++ b/yarn.lock @@ -389,10 +389,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.20.13", "@babel/parser@^7.20.7": - version "7.20.13" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.13.tgz#ddf1eb5a813588d2fb1692b70c6fce75b945c088" - integrity sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw== +"@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.20.13", "@babel/parser@^7.20.15", "@babel/parser@^7.20.7": + version "7.20.15" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.15.tgz#eec9f36d8eaf0948bb88c87a46784b5ee9fd0c89" + integrity sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -25337,14 +25337,7 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@^2.6.2: +rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== From c2476d240e5a5a979af215057bb7f2bd40b9f6fe Mon Sep 17 00:00:00 2001 From: "Quynh Nguyen (Quinn)" <43350163+qn895@users.noreply.github.com> Date: Mon, 13 Feb 2023 20:43:46 -0600 Subject: [PATCH 152/203] [ML] Fixes incorrect feature importance visualization for Data Frame Analytics classification (#150816) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/data_grid/data_grid.tsx | 2 +- .../decision_path_classification.tsx | 11 +- .../use_classification_path_data.test.tsx | 325 ++++++++++++------ .../use_classification_path_data.tsx | 4 + .../results_view_content.ts | 7 + .../services/ml/common_data_grid.ts | 15 + .../ml/data_frame_analytics_results.ts | 4 + 7 files changed, 268 insertions(+), 100 deletions(-) diff --git a/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx b/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx index b2fceb58edfa4..95a7955ec9a39 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx +++ b/x-pack/plugins/ml/public/application/components/data_grid/data_grid.tsx @@ -124,7 +124,7 @@ export const DataGrid: FC = memo( analysisType === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION ) { if (schema === 'featureImportance') { - const row = data[rowIndex]; + const row = data[rowIndex - pagination.pageIndex * pagination.pageSize]; if (!row) return
; // if resultsField for some reason is not available then use ml const mlResultsField = resultsField ?? DEFAULT_RESULTS_FIELD; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_classification.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_classification.tsx index d10755b32d7a7..45f19ad7b76f7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_classification.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/decision_path_classification.tsx @@ -21,6 +21,7 @@ import type { } from '../../../../../../../common/types/feature_importance'; import { DecisionPathChart } from './decision_path_chart'; import { MissingDecisionPathCallout } from './missing_decision_path_callout'; +import { TopClass } from '../../../../../../../common/types/feature_importance'; interface ClassificationDecisionPathProps { predictedValue: string | boolean; @@ -42,12 +43,20 @@ export const ClassificationDecisionPath: FC = ( const [currentClass, setCurrentClass] = useState( getStringBasedClassName(topClasses[0].class_name) ); + const selectedClass = topClasses.find( + (t) => getStringBasedClassName(t.class_name) === getStringBasedClassName(currentClass) + ) as TopClass; + const predictedProbabilityForCurrentClass = selectedClass + ? selectedClass.class_probability + : undefined; + const { decisionPathData } = useDecisionPathData({ baseline, featureImportance, predictedValue: currentClass, - predictedProbability, + predictedProbability: predictedProbabilityForCurrentClass, }); + const options = useMemo(() => { const predictionValueStr = getStringBasedClassName(predictedValue); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.test.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.test.tsx index 70c62294cae00..53ae0daff084a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.test.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.test.tsx @@ -10,9 +10,10 @@ import { buildRegressionDecisionPathData, } from './use_classification_path_data'; import type { FeatureImportance } from '../../../../../../../common/types/feature_importance'; +import { roundToDecimalPlace } from '../../../../../formatters/round_to_decimal_place'; describe('buildClassificationDecisionPathData()', () => { - test('should return correct prediction probability for binary classification', () => { + test('returns correct prediction probability for binary classification', () => { const expectedResults = [ { className: 'yes', probability: 0.28564605871278403 }, { className: 'no', probability: 1 - 0.28564605871278403 }, @@ -71,139 +72,170 @@ describe('buildClassificationDecisionPathData()', () => { expect(result).toHaveLength(featureNames.length); expect(featureNames).toContain(result![0][0]); expect(result![0]).toHaveLength(3); + // Top shown result should equal expected probability expect(result![0][2]).toEqual(probability); + // Make sure probability (result[0]) is always less than 1 + expect(result?.every((r) => r[2] <= 1)).toEqual(true); } }); - test('should return correct prediction probability for multiclass classification', () => { - const expectedResults = [{ className: 1, probability: 0.3551929251919077 }]; + test('returns correct prediction probability & accounts for "other" residual probability for binary classification (boolean)', () => { + const expectedResults = [ + { + class_score: 0.1940750725280285, + class_probability: 0.9034630008985833, + // boolean class name should be converted to string 'True'/'False' + class_name: false, + }, + { + class_score: 0.09653699910141661, + class_probability: 0.09653699910141661, + class_name: true, + }, + ]; const baselinesData = { classes: [ { - class_name: 0, - baseline: 0.1845274610161167, + class_name: false, + baseline: 2.418789842558993, }, { - class_name: 1, - baseline: 0.1331813646384272, - }, - { - class_name: 2, - baseline: 0.1603600353308416, + class_name: true, + baseline: -2.418789842558993, }, ], }; const featureImportanceData: FeatureImportance[] = [ { - feature_name: 'AvgTicketPrice', + feature_name: 'DestWeather', classes: [ - { importance: 0.34413545865934353, class_name: 0 }, - { importance: 0.4781222770431657, class_name: 1 }, - { importance: 0.31847802693610877, class_name: 2 }, + { + importance: 0.5555510565764721, + // string class names 'true'/'false' should be converted to string 'True'/'False' + class_name: 'false', + }, + { + importance: -0.5555510565764721, + class_name: 'true', + }, ], }, { - feature_name: 'Cancelled', + feature_name: 'OriginWeather', classes: [ - { importance: 0.0002822015809810556, class_name: 0 }, - { importance: -0.0033337017702255597, class_name: 1 }, - { importance: 0.0020744732163668696, class_name: 2 }, + { + importance: 0.31139248413258486, + class_name: 'false', + }, + { + importance: -0.31139248413258486, + class_name: 'true', + }, ], }, { - feature_name: 'DistanceKilometers', + feature_name: 'OriginAirportID', classes: [ - { importance: 0.028472232240294063, class_name: 0 }, - { importance: 0.04119838646840895, class_name: 1 }, - { importance: 0.0662663363977551, class_name: 2 }, + { + importance: 0.2895740692218651, + class_name: 'false', + }, + { + importance: -0.2895740692218651, + class_name: 'true', + }, + ], + }, + { + feature_name: 'DestAirportID', + classes: [ + { + importance: 0.1297619730881764, + class_name: 'false', + }, + { + importance: -0.1297619730881764, + class_name: 'true', + }, + ], + }, + { + feature_name: 'hour_of_day', + classes: [ + { + importance: -0.10596307272294636, + class_name: 'false', + }, + { + importance: 0.10596307272294636, + class_name: 'true', + }, ], }, ]; const featureNames = featureImportanceData.map((d) => d.feature_name); - for (const { className, probability } of expectedResults) { + for (const { class_name: className, class_probability: probability } of expectedResults) { const result = buildClassificationDecisionPathData({ baselines: baselinesData.classes, featureImportance: featureImportanceData, currentClass: className, + predictedProbability: probability, }); + expect(result).toBeDefined(); - expect(result).toHaveLength(featureNames.length); + // Should add an 'other' field + expect(result).toHaveLength(featureNames.length + 1); expect(featureNames).toContain(result![0][0]); expect(result![0]).toHaveLength(3); + // Top shown result should equal expected probability expect(result![0][2]).toEqual(probability); + // Make sure probability (result[0]) is always less than 1 + expect(result?.every((r) => r[2] <= 1)).toEqual(true); } }); -}); -describe('buildRegressionDecisionPathData()', () => { - test('should return correct decision path', () => { - const predictedValue = 0.008000000000000005; - const baseline = 0.01570748450465414; - const featureImportanceData: FeatureImportance[] = [ - { feature_name: 'g1', importance: -0.01171550599313763 }, - { feature_name: 'tau4', importance: -0.01190799086101345 }, - ]; - const expectedFeatures = [ - ...featureImportanceData.map((d) => d.feature_name), - 'other', - 'baseline', - ]; - const result = buildRegressionDecisionPathData({ - baseline, - featureImportance: featureImportanceData, - predictedValue: 0.008, - }); - expect(result).toBeDefined(); - expect(result).toHaveLength(expectedFeatures.length); - expect(result![0]).toHaveLength(3); - expect(result![0][2]).toEqual(predictedValue); - }); - - test('buildClassificationDecisionPathData() should return correct prediction probability for binary classification', () => { - const expectedResults = [ - { className: 'yes', probability: 0.28564605871278403 }, - { className: 'no', probability: 1 - 0.28564605871278403 }, - ]; + test('returns correct prediction probability for multiclass classification', () => { + const expectedResults = [{ className: 1, probability: 0.3551929251919077 }]; const baselinesData = { classes: [ { - class_name: 'no', - baseline: 3.228256450715653, + class_name: 0, + baseline: 0.1845274610161167, }, { - class_name: 'yes', - baseline: -3.228256450715653, + class_name: 1, + baseline: 0.1331813646384272, + }, + { + class_name: 2, + baseline: 0.1603600353308416, }, ], }; const featureImportanceData: FeatureImportance[] = [ { - feature_name: 'duration', - classes: [ - { importance: 2.9932577725789455, class_name: 'yes' }, - { importance: -2.9932577725789455, class_name: 'no' }, - ], - }, - { - feature_name: 'job', + feature_name: 'AvgTicketPrice', classes: [ - { importance: -0.8023759403354496, class_name: 'yes' }, - { importance: 0.8023759403354496, class_name: 'no' }, + { importance: 0.34413545865934353, class_name: 0 }, + { importance: 0.4781222770431657, class_name: 1 }, + { importance: 0.31847802693610877, class_name: 2 }, ], }, { - feature_name: 'poutcome', + feature_name: 'Cancelled', classes: [ - { importance: 0.43319318839128396, class_name: 'yes' }, - { importance: -0.43319318839128396, class_name: 'no' }, + { importance: 0.0002822015809810556, class_name: 0 }, + { importance: -0.0033337017702255597, class_name: 1 }, + { importance: 0.0020744732163668696, class_name: 2 }, ], }, { - feature_name: 'housing', + feature_name: 'DistanceKilometers', classes: [ - { importance: -0.3124436380550531, class_name: 'yes' }, - { importance: 0.3124436380550531, class_name: 'no' }, + { importance: 0.028472232240294063, class_name: 0 }, + { importance: 0.04119838646840895, class_name: 1 }, + { importance: 0.0662663363977551, class_name: 2 }, ], }, ]; @@ -219,67 +251,164 @@ describe('buildRegressionDecisionPathData()', () => { expect(result).toHaveLength(featureNames.length); expect(featureNames).toContain(result![0][0]); expect(result![0]).toHaveLength(3); + // Top shown result should equal expected probability expect(result![0][2]).toEqual(probability); + // Make sure probability (result[0]) is always less than 1 + expect(result?.every((r) => r[2] <= 1)).toEqual(true); } }); - test('buildClassificationDecisionPathData() should return correct prediction probability for multiclass classification', () => { - const expectedResults = [{ className: 1, probability: 0.3551929251919077 }]; + test('returns correct prediction probability for multiclass classification with "other"', () => { + const expectedResults = [ + { + class_score: 0.2653792729907741, + class_probability: 0.995901728296372, + class_name: 'Iris-setosa', + }, + { + class_score: 0.002499393297421585, + class_probability: 0.002499393297421585, + class_name: 'Iris-versicolor', + }, + { + class_score: 0.0015399995493349922, + class_probability: 0.0015988784062062893, + class_name: 'Iris-virginica', + }, + ]; const baselinesData = { classes: [ { - class_name: 0, - baseline: 0.1845274610161167, + class_name: 'Iris-setosa', + baseline: -0.25145851617108084, }, { - class_name: 1, - baseline: 0.1331813646384272, + class_name: 'Iris-versicolor', + baseline: 0.46014588263093625, }, { - class_name: 2, - baseline: 0.1603600353308416, + class_name: 'Iris-virginica', + baseline: -0.20868736645984168, }, ], }; const featureImportanceData: FeatureImportance[] = [ { - feature_name: 'AvgTicketPrice', + feature_name: 'petal_length', classes: [ - { importance: 0.34413545865934353, class_name: 0 }, - { importance: 0.4781222770431657, class_name: 1 }, - { importance: 0.31847802693610877, class_name: 2 }, + { + importance: 2.4826228835057464, + class_name: 'Iris-setosa', + }, + { + importance: -0.5861671310095675, + class_name: 'Iris-versicolor', + }, + { + importance: -1.8964557524961734, + class_name: 'Iris-virginica', + }, ], }, { - feature_name: 'Cancelled', + feature_name: 'petal_width', classes: [ - { importance: 0.0002822015809810556, class_name: 0 }, - { importance: -0.0033337017702255597, class_name: 1 }, - { importance: 0.0020744732163668696, class_name: 2 }, + { + importance: 1.4568820749127243, + class_name: 'Iris-setosa', + }, + { + importance: -0.9431104132306853, + class_name: 'Iris-versicolor', + }, + { + importance: -0.5137716616820365, + class_name: 'Iris-virginica', + }, ], }, { - feature_name: 'DistanceKilometers', + feature_name: 'sepal_width', classes: [ - { importance: 0.028472232240294063, class_name: 0 }, - { importance: 0.04119838646840895, class_name: 1 }, - { importance: 0.0662663363977551, class_name: 2 }, + { + importance: 0.3508206289936615, + class_name: 'Iris-setosa', + }, + { + importance: 0.023074695691663594, + class_name: 'Iris-versicolor', + }, + { + importance: -0.3738953246853245, + class_name: 'Iris-virginica', + }, + ], + }, + { + feature_name: 'sepal_length', + classes: [ + { + importance: -0.027900272907686156, + class_name: 'Iris-setosa', + }, + { + importance: 0.13376776004064217, + class_name: 'Iris-versicolor', + }, + { + importance: -0.1058674871329558, + class_name: 'Iris-virginica', + }, ], }, ]; const featureNames = featureImportanceData.map((d) => d.feature_name); - for (const { className, probability } of expectedResults) { + for (const { + class_name: className, + class_probability: classPredictedProbability, + } of expectedResults) { const result = buildClassificationDecisionPathData({ baselines: baselinesData.classes, featureImportance: featureImportanceData, currentClass: className, + predictedProbability: classPredictedProbability, }); expect(result).toBeDefined(); - expect(result).toHaveLength(featureNames.length); + // Result accounts for 'other' or residual importance + expect(result).toHaveLength(featureNames.length + 1); expect(featureNames).toContain(result![0][0]); expect(result![0]).toHaveLength(3); - expect(result![0][2]).toEqual(probability); + expect(roundToDecimalPlace(result![0][2], 3)).toEqual( + roundToDecimalPlace(classPredictedProbability, 3) + ); + // Make sure probability (result[0]) is always less than 1 + expect(result?.every((r) => r[2] <= 1)).toEqual(true); } }); }); +describe('buildRegressionDecisionPathData()', () => { + test('returns correct decision path', () => { + const predictedValue = 0.008000000000000005; + const baseline = 0.01570748450465414; + const featureImportanceData: FeatureImportance[] = [ + { feature_name: 'g1', importance: -0.01171550599313763 }, + { feature_name: 'tau4', importance: -0.01190799086101345 }, + ]; + const expectedFeatures = [ + ...featureImportanceData.map((d) => d.feature_name), + 'other', + 'baseline', + ]; + + const result = buildRegressionDecisionPathData({ + baseline, + featureImportance: featureImportanceData, + predictedValue: 0.008, + }); + expect(result).toBeDefined(); + expect(result).toHaveLength(expectedFeatures.length); + expect(result![0]).toHaveLength(3); + expect(result![0][2]).toEqual(predictedValue); + }); +}); diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.tsx index ad9f0b3d0bb71..65954578db6ed 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/feature_importance/use_classification_path_data.tsx @@ -58,6 +58,10 @@ export const getStringBasedClassName = (v: string | boolean | undefined | number if (typeof v === 'boolean') { return v ? 'True' : 'False'; } + + if (v === 'true') return 'True'; + if (v === 'false') return 'False'; + if (typeof v === 'number') { return v.toString(); } diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts index f3e6eac011b73..308ec43593c0c 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts @@ -294,6 +294,13 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsResults.assertFeatureImportancePopoverContent(); }); + it('should display the feature importance decision path after changing page', async () => { + await ml.dataFrameAnalyticsResults.selectResultsTablePage(3); + await ml.dataFrameAnalyticsResults.assertResultsTableNotEmpty(); + await ml.dataFrameAnalyticsResults.openFeatureImportancePopover(); + await ml.dataFrameAnalyticsResults.assertFeatureImportancePopoverContent(); + }); + it('should display the histogram charts', async () => { await ml.testExecution.logTestStep( 'displays the histogram charts when option is enabled' diff --git a/x-pack/test/functional/services/ml/common_data_grid.ts b/x-pack/test/functional/services/ml/common_data_grid.ts index f118af7090b43..9950d6b8f7205 100644 --- a/x-pack/test/functional/services/ml/common_data_grid.ts +++ b/x-pack/test/functional/services/ml/common_data_grid.ts @@ -219,5 +219,20 @@ export function MachineLearningCommonDataGridProvider({ getService }: FtrProvide await browser.pressKeys(browser.keys.ESCAPE); }); }, + + async assertActivePage(tableSubj: string, expectedPage: number) { + const table = await testSubjects.find(tableSubj); + const pagination = await table.findByClassName('euiPagination__list'); + const activePage = await pagination.findByCssSelector( + '.euiPaginationButton[aria-current] .euiButtonEmpty__text' + ); + const text = await activePage.getVisibleText(); + expect(text).to.eql(expectedPage); + }, + + async selectPage(tableSubj: string, page: number) { + await testSubjects.click(`${tableSubj} > pagination-button-${page - 1}`); + await this.assertActivePage(tableSubj, page); + }, }; } diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts index a4378636673de..0fc99e1e032a1 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_results.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_results.ts @@ -57,6 +57,10 @@ export function MachineLearningDataFrameAnalyticsResultsProvider( await testSubjects.existOrFail('mlExplorationDataGrid loaded', { timeout: 5000 }); }, + async selectResultsTablePage(page: number) { + await commonDataGrid.selectPage('mlExplorationDataGrid loaded', page); + }, + async assertResultsTableTrainingFiltersExist() { await testSubjects.existOrFail('mlDFAnalyticsExplorationQueryBarFilterButtons', { timeout: 5000, From 288054ddc0359feffaf5c7d982c52ea375f4850d Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Tue, 14 Feb 2023 06:36:37 +0100 Subject: [PATCH 153/203] [Discover] Refactor app state functionality to getDiscoverAppStateContainer (#149389) --- .../components/top_nav/get_top_nav_links.tsx | 2 +- .../top_nav/on_save_search.test.tsx | 71 ++--- .../components/top_nav/on_save_search.tsx | 4 +- .../main/hooks/use_adhoc_data_views.ts | 2 +- .../main/hooks/use_discover_state.ts | 114 +------- .../use_test_based_query_language.test.ts | 97 +++---- .../hooks/use_text_based_query_language.ts | 2 +- .../hooks/utils/build_state_subscribe.test.ts | 134 +++++++++ .../main/hooks/utils/build_state_subscribe.ts | 83 ++++++ .../main/hooks/utils/change_data_view.test.ts | 48 ++++ .../main/hooks/utils/change_data_view.ts | 55 ++++ .../discover_app_state_container.test.ts | 51 ++++ .../services/discover_app_state_container.ts | 268 +++++++++++++++++- .../main/services/discover_state.test.ts | 32 ++- .../main/services/discover_state.ts | 260 +++-------------- .../main/utils/cleanup_url_state.test.ts | 2 +- .../main/utils/cleanup_url_state.ts | 3 +- .../hooks/use_confirm_persistence_prompt.ts | 2 +- src/plugins/discover/public/utils/add_log.ts | 21 ++ .../discover/public/utils/get_sharing_data.ts | 6 +- 20 files changed, 806 insertions(+), 451 deletions(-) create mode 100644 src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.test.ts create mode 100644 src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.ts create mode 100644 src/plugins/discover/public/application/main/hooks/utils/change_data_view.test.ts create mode 100644 src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts create mode 100644 src/plugins/discover/public/application/main/services/discover_app_state_container.test.ts create mode 100644 src/plugins/discover/public/utils/add_log.ts diff --git a/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx b/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx index 0036b517c0eb9..59723e5b1225f 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/get_top_nav_links.tsx @@ -181,7 +181,7 @@ export const getTopNavLinks = ({ defaultMessage: 'Untitled discover search', }), }, - isDirty: !savedSearch.id || state.isAppStateDirty(), + isDirty: !savedSearch.id || state.appState.hasChanged(), showPublicUrlSwitch, onClose: () => { anchorElement?.focus(); diff --git a/src/plugins/discover/public/application/main/components/top_nav/on_save_search.test.tsx b/src/plugins/discover/public/application/main/components/top_nav/on_save_search.test.tsx index f8199fadd2e61..a7efab7d984a9 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/on_save_search.test.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/on_save_search.test.tsx @@ -14,35 +14,35 @@ jest.mock('../../utils/persist_saved_search', () => ({ import { onSaveSearch } from './on_save_search'; import { dataViewMock } from '../../../../__mocks__/data_view'; import { savedSearchMock } from '../../../../__mocks__/saved_search'; -import { DiscoverServices } from '../../../../build_services'; -import { DiscoverStateContainer } from '../../services/discover_state'; -import { i18nServiceMock } from '@kbn/core/public/mocks'; +import { getDiscoverStateContainer } from '../../services/discover_state'; import { ReactElement } from 'react'; import { discoverServiceMock } from '../../../../__mocks__/services'; import * as persistSavedSearchUtils from '../../utils/persist_saved_search'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { createBrowserHistory } from 'history'; + +function getStateContainer() { + const savedSearch = savedSearchMock; + const history = createBrowserHistory(); + const stateContainer = getDiscoverStateContainer({ + savedSearch, + services: discoverServiceMock, + history, + }); + stateContainer.appState.getState = jest.fn(() => ({ + rowsPerPage: 250, + })); + return stateContainer; +} describe('onSaveSearch', () => { it('should call showSaveModal', async () => { - const serviceMock = { - core: { - i18n: i18nServiceMock.create(), - }, - } as unknown as DiscoverServices; - const stateMock = { - appState: { - getState: () => ({ - rowsPerPage: 250, - }), - }, - } as unknown as DiscoverStateContainer; - await onSaveSearch({ dataView: dataViewMock, navigateTo: jest.fn(), savedSearch: savedSearchMock, - services: serviceMock, - state: stateMock, + services: discoverServiceMock, + state: getStateContainer(), updateAdHocDataViewId: jest.fn(), }); @@ -50,14 +50,6 @@ describe('onSaveSearch', () => { }); it('should pass tags to the save modal', async () => { - const serviceMock = discoverServiceMock; - const stateMock = { - appState: { - getState: () => ({ - rowsPerPage: 250, - }), - }, - } as unknown as DiscoverStateContainer; let saveModal: ReactElement | undefined; jest.spyOn(savedObjectsPlugin, 'showSaveModal').mockImplementationOnce((modal) => { saveModal = modal; @@ -69,23 +61,14 @@ describe('onSaveSearch', () => { ...savedSearchMock, tags: ['tag1', 'tag2'], }, - services: serviceMock, - state: stateMock, + services: discoverServiceMock, + state: getStateContainer(), updateAdHocDataViewId: jest.fn(), }); expect(saveModal?.props.tags).toEqual(['tag1', 'tag2']); }); it('should update the saved search tags', async () => { - const serviceMock = discoverServiceMock; - const stateMock = { - appState: { - getState: () => ({ - rowsPerPage: 250, - }), - }, - resetInitialAppState: jest.fn(), - } as unknown as DiscoverStateContainer; let saveModal: ReactElement | undefined; jest.spyOn(savedObjectsPlugin, 'showSaveModal').mockImplementationOnce((modal) => { saveModal = modal; @@ -98,8 +81,8 @@ describe('onSaveSearch', () => { dataView: dataViewMock, navigateTo: jest.fn(), savedSearch, - services: serviceMock, - state: stateMock, + services: discoverServiceMock, + state: getStateContainer(), updateAdHocDataViewId: jest.fn(), }); expect(savedSearch.tags).toEqual(['tag1', 'tag2']); @@ -122,14 +105,6 @@ describe('onSaveSearch', () => { it('should not update tags if savedObjectsTagging is undefined', async () => { const serviceMock = discoverServiceMock; - const stateMock = { - appState: { - getState: () => ({ - rowsPerPage: 250, - }), - }, - resetInitialAppState: jest.fn(), - } as unknown as DiscoverStateContainer; let saveModal: ReactElement | undefined; jest.spyOn(savedObjectsPlugin, 'showSaveModal').mockImplementationOnce((modal) => { saveModal = modal; @@ -146,7 +121,7 @@ describe('onSaveSearch', () => { ...serviceMock, savedObjectsTagging: undefined, }, - state: stateMock, + state: getStateContainer(), updateAdHocDataViewId: jest.fn(), }); expect(savedSearch.tags).toEqual(['tag1', 'tag2']); diff --git a/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx b/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx index 237fc2b4ab574..4d88e48b8adf5 100644 --- a/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx +++ b/src/plugins/discover/public/application/main/components/top_nav/on_save_search.tsx @@ -53,7 +53,7 @@ async function saveDataSource({ navigateTo(`/view/${encodeURIComponent(id)}`); } else { // Update defaults so that "reload saved query" functions correctly - state.resetAppState(savedSearch); + state.appState.resetWithSavedSearch(savedSearch); services.chrome.docTitle.change(savedSearch.title!); setBreadcrumbsTitle( @@ -169,7 +169,7 @@ export async function onSaveSearch({ savedSearch.tags = currentTags; } } else { - state.resetInitialAppState(); + state.appState.resetInitialState(); } onSaveCb?.(); return response; diff --git a/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts b/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts index c87c13b0e9fb7..31e96f01a2b74 100644 --- a/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts +++ b/src/plugins/discover/public/application/main/hooks/use_adhoc_data_views.ts @@ -63,7 +63,7 @@ export const useAdHocDataViews = ({ updateFiltersReferences(prevDataView, newDataView); stateContainer.actions.replaceAdHocDataViewWithId(prevDataView.id!, newDataView); - await stateContainer.replaceUrlAppState({ index: newDataView.id }); + await stateContainer.appState.update({ index: newDataView.id }, true); setUrlTracking(newDataView); return newDataView; 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 f5b3949e103a9..1170629142dae 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,12 +6,12 @@ * Side Public License, v 1. */ import { useMemo, useEffect, useState, useCallback } from 'react'; -import { isEqual } from 'lodash'; import { History } from 'history'; import { isOfAggregateQueryType } from '@kbn/es-query'; import { type DataView, 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 { buildStateSubscribe } from './utils/build_state_subscribe'; +import { changeDataView } from './utils/change_data_view'; import { useSearchSession } from './use_search_session'; import { FetchStatus } from '../../types'; import { useTextBasedQueryLanguage } from './use_text_based_query_language'; @@ -19,9 +19,6 @@ import { useUrlTracking } from './use_url_tracking'; import { getDiscoverStateContainer } from '../services/discover_state'; import { getStateDefaults } from '../utils/get_state_defaults'; import { DiscoverServices } from '../../../build_services'; -import { loadDataView, resolveDataView } from '../utils/resolve_data_view'; -import { MODIFY_COLUMNS_ON_SWITCH, SORT_DEFAULT_ORDER_SETTING } from '../../../../common'; -import { getDataViewAppState } from '../utils/get_switch_data_view_app_state'; import { DataTableRecord } from '../../../types'; import { restoreStateFromSavedSearch } from '../../../services/saved_searches/restore_from_saved_search'; import { useAdHocDataViews } from './use_adhoc_data_views'; @@ -37,8 +34,7 @@ export function useDiscoverState({ history: History; setExpandedDoc: (doc?: DataTableRecord) => void; }) { - const { uiSettings, data, filterManager, dataViews, toastNotifications, trackUiMetric } = - services; + const { data, filterManager, dataViews, toastNotifications, trackUiMetric } = services; const dataView = savedSearch.searchSource.getField('index')!; @@ -63,7 +59,7 @@ export function useDiscoverState({ const { setUrlTracking } = useUrlTracking(savedSearch, dataView); - const { appState, replaceUrlAppState, searchSessionManager } = stateContainer; + const { appState, searchSessionManager } = stateContainer; const [state, setState] = useState(appState.getState()); @@ -142,109 +138,21 @@ export function useDiscoverState({ * Track state changes that should trigger a fetch */ useEffect(() => { - const unsubscribe = appState.subscribe(async (nextState) => { - const { hideChart, interval, breakdownField, sort, index } = state; - // Cast to boolean to avoid false positives when comparing - // undefined and false, which would trigger a refetch - const chartDisplayChanged = Boolean(nextState.hideChart) !== Boolean(hideChart); - const chartIntervalChanged = nextState.interval !== interval; - const breakdownFieldChanged = nextState.breakdownField !== breakdownField; - const docTableSortChanged = !isEqual(nextState.sort, sort); - const dataViewChanged = !isEqual(nextState.index, index); - // NOTE: this is also called when navigating from discover app to context app - if (nextState.index && dataViewChanged) { - /** - * Without resetting the fetch state, e.g. a time column would be displayed when switching - * from a data view without to a data view with time filter for a brief moment - * That's because appState is updated before savedSearchData$ - * The following line of code catches this, but should be improved - */ - const nextDataViewData = await loadDataView( - services.dataViews, - services.uiSettings, - nextState.index - ); - const nextDataView = resolveDataView( - nextDataViewData, - savedSearch.searchSource, - services.toastNotifications - ); - - // If the requested data view is not found, don't try to load it, - // and instead reset the app state to the fallback data view - if (!nextDataViewData.stateValFound) { - replaceUrlAppState({ index: nextDataView.id }); - return; - } - savedSearch.searchSource.setField('index', nextDataView); - reset(); - stateContainer.actions.setDataView(nextDataView); - } - - if ( - dataViewChanged && - stateContainer.dataState.initialFetchStatus === FetchStatus.UNINITIALIZED - ) { - // stop execution if given data view has changed, and it's not configured to initially start a search in Discover - return; - } - - if ( - chartDisplayChanged || - chartIntervalChanged || - breakdownFieldChanged || - docTableSortChanged - ) { - refetch$.next(undefined); - } - - setState(nextState); - }); + const unsubscribe = appState.subscribe( + buildStateSubscribe({ stateContainer, savedSearch, setState }) + ); return () => unsubscribe(); - }, [ - services, - appState, - state, - refetch$, - data$, - reset, - savedSearch, - replaceUrlAppState, - stateContainer, - ]); + }, [appState, savedSearch, services, stateContainer]); /** * Function triggered when user changes data view in the sidebar */ const onChangeDataView = useCallback( async (id: string) => { - const nextDataView = await dataViews.get(id); - if (nextDataView && dataView) { - const nextAppState = getDataViewAppState( - dataView, - nextDataView, - state.columns || [], - (state.sort || []) as SortOrder[], - uiSettings.get(MODIFY_COLUMNS_ON_SWITCH), - uiSettings.get(SORT_DEFAULT_ORDER_SETTING), - state.query - ); - setUrlTracking(nextDataView); - stateContainer.setAppState(nextAppState); - } + await changeDataView(id, { services, discoverState: stateContainer, setUrlTracking }); setExpandedDoc(undefined); }, - [ - setUrlTracking, - uiSettings, - dataView, - dataViews, - setExpandedDoc, - state.columns, - state.query, - state.sort, - stateContainer, - ] + [services, setExpandedDoc, setUrlTracking, stateContainer] ); /** @@ -271,7 +179,7 @@ export function useDiscoverState({ timefilter: services.timefilter, }); - await stateContainer.replaceUrlAppState(newAppState); + await stateContainer.appState.update(newAppState, true); setState(newAppState); }, [services, dataView, stateContainer] 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 index 0f1b6488f3681..b596e2bc06c40 100644 --- 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 @@ -19,16 +19,15 @@ 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'; -import { AppState } from '../services/discover_app_state_container'; import { getDiscoverStateMock } from '../../../__mocks__/discover_state.mock'; function getHookProps( - replaceUrlAppState: (newState: Partial) => Promise, query: AggregateQuery | Query | undefined, dataViewsService?: DataViewsContract ) { + const replaceUrlState = jest.fn(); const stateContainer = getDiscoverStateMock({ isTimeBased: true }); - stateContainer.replaceUrlAppState = replaceUrlAppState; + stateContainer.appState.replaceUrlState = replaceUrlState; stateContainer.setAppState({ columns: [] }); stateContainer.internalState.transitions.setSavedDataViews([dataViewMock as DataViewListItem]); @@ -45,6 +44,7 @@ function getHookProps( dataViews: dataViewsService ?? discoverServiceMock.dataViews, stateContainer, savedSearch: savedSearchMock, + replaceUrlState, }; } const query = { sql: 'SELECT * from the-data-view-title' }; @@ -63,37 +63,35 @@ const msgComplete = { 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; + const props = getHookProps(query); + const { documents$, replaceUrlState } = props; renderHook(() => useTextBasedQueryLanguage(props)); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); - expect(replaceUrlAppState).toHaveBeenCalledWith({ index: 'the-data-view-id' }); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); + expect(replaceUrlState).toHaveBeenCalledWith({ index: 'the-data-view-id' }); - replaceUrlAppState.mockReset(); + replaceUrlState.mockReset(); documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); await waitFor(() => { - expect(replaceUrlAppState).toHaveBeenCalledWith({ + expect(replaceUrlState).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; + const props = getHookProps(query); + const { documents$, replaceUrlState } = props; renderHook(() => useTextBasedQueryLanguage(props)); documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(2)); - replaceUrlAppState.mockReset(); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + replaceUrlState.mockReset(); documents$.next({ recordRawType: RecordRawType.PLAIN, @@ -107,25 +105,24 @@ describe('useTextBasedQueryLanguage', () => { ], query: { sql: 'SELECT field1 from the-data-view-title' }, }); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); await waitFor(() => { - expect(replaceUrlAppState).toHaveBeenCalledWith({ + expect(replaceUrlState).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; + const props = getHookProps(query); + const { documents$, replaceUrlState } = props; renderHook(() => useTextBasedQueryLanguage(props)); documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(2)); - replaceUrlAppState.mockReset(); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + replaceUrlState.mockReset(); documents$.next({ recordRawType: RecordRawType.PLAIN, @@ -139,8 +136,8 @@ describe('useTextBasedQueryLanguage', () => { ], query: { sql: 'SELECT field1 from the-data-view-title' }, }); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); - replaceUrlAppState.mockReset(); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); + replaceUrlState.mockReset(); documents$.next({ recordRawType: RecordRawType.PLAIN, @@ -156,21 +153,20 @@ describe('useTextBasedQueryLanguage', () => { }); await waitFor(() => { - expect(replaceUrlAppState).toHaveBeenCalledWith({ + expect(replaceUrlState).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; + const props = getHookProps(query); + const { documents$, replaceUrlState } = props; renderHook(() => useTextBasedQueryLanguage(props)); documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(2)); - replaceUrlAppState.mockReset(); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + replaceUrlState.mockReset(); documents$.next({ recordRawType: RecordRawType.DOCUMENT, @@ -198,7 +194,7 @@ describe('useTextBasedQueryLanguage', () => { }); await waitFor(() => { - expect(replaceUrlAppState).toHaveBeenCalledWith({ + expect(replaceUrlState).toHaveBeenCalledWith({ index: 'the-data-view-id', columns: ['field1'], }); @@ -206,12 +202,11 @@ describe('useTextBasedQueryLanguage', () => { }); test('it should not overwrite existing state columns on initial fetch', async () => { - const replaceUrlAppState = jest.fn(); - const props = getHookProps(replaceUrlAppState, query); + const props = getHookProps(query); props.stateContainer.appState.getState = jest.fn(() => { return { columns: ['field1'], index: 'the-data-view-id' }; }); - const { documents$ } = props; + const { documents$, replaceUrlState } = props; renderHook(() => useTextBasedQueryLanguage(props)); documents$.next({ @@ -239,19 +234,18 @@ describe('useTextBasedQueryLanguage', () => { ], query: { sql: 'SELECT field1 from the-data-view-title' }, }); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); - expect(replaceUrlAppState).toHaveBeenCalledWith({ + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); + expect(replaceUrlState).toHaveBeenCalledWith({ columns: ['field1'], }); }); test('it should not overwrite state column when successfully fetching after an error fetch', async () => { - const replaceUrlAppState = jest.fn(); - const props = getHookProps(replaceUrlAppState, query); + const props = getHookProps(query); props.stateContainer.appState.getState = jest.fn(() => { return { columns: [], index: 'the-data-view-id' }; }); - const { documents$ } = props; + const { documents$, replaceUrlState } = props; renderHook(() => useTextBasedQueryLanguage(props)); documents$.next({ @@ -259,7 +253,7 @@ describe('useTextBasedQueryLanguage', () => { fetchStatus: FetchStatus.LOADING, query: { sql: 'SELECT * from the-data-view-title WHERE field1=2' }, }); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(0)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(0)); documents$.next({ recordRawType: RecordRawType.PLAIN, fetchStatus: FetchStatus.COMPLETE, @@ -272,11 +266,11 @@ describe('useTextBasedQueryLanguage', () => { ], query: { sql: 'SELECT * from the-data-view-title WHERE field1=2' }, }); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); props.stateContainer.appState.getState = jest.fn(() => { return { columns: ['field1', 'field2'], index: 'the-data-view-id' }; }); - replaceUrlAppState.mockReset(); + replaceUrlState.mockReset(); documents$.next({ recordRawType: RecordRawType.PLAIN, @@ -308,14 +302,13 @@ describe('useTextBasedQueryLanguage', () => { query: { sql: 'SELECT field1 from the-data-view-title' }, }); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); - expect(replaceUrlAppState).toHaveBeenCalledWith({ + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); + expect(replaceUrlState).toHaveBeenCalledWith({ columns: ['field1'], }); }); test('changing a text based query with an index pattern that not corresponds to a dataview should return results', async () => { - const replaceUrlAppState = jest.fn(); const dataViewsCreateMock = discoverServiceMock.dataViews.create as jest.Mock; dataViewsCreateMock.mockImplementation(() => ({ ...dataViewMock, @@ -324,14 +317,14 @@ describe('useTextBasedQueryLanguage', () => { ...discoverServiceMock.dataViews, create: dataViewsCreateMock, }; - const props = getHookProps(replaceUrlAppState, query, dataViewsService); - const { documents$ } = props; + const props = getHookProps(query, dataViewsService); + const { documents$, replaceUrlState } = props; renderHook(() => useTextBasedQueryLanguage(props)); documents$.next(msgComplete); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(2)); - replaceUrlAppState.mockReset(); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(2)); + replaceUrlState.mockReset(); documents$.next({ recordRawType: RecordRawType.PLAIN, @@ -345,10 +338,10 @@ describe('useTextBasedQueryLanguage', () => { ], query: { sql: 'SELECT field1 from the-data-view-*' }, }); - await waitFor(() => expect(replaceUrlAppState).toHaveBeenCalledTimes(1)); + await waitFor(() => expect(replaceUrlState).toHaveBeenCalledTimes(1)); await waitFor(() => { - expect(replaceUrlAppState).toHaveBeenCalledWith({ + expect(replaceUrlState).toHaveBeenCalledWith({ index: 'the-data-view-id', 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 index b47c7145904bf..5e2eb33efdbe9 100644 --- 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 @@ -116,7 +116,7 @@ export function useTextBasedQueryLanguage({ ...(addDataViewToState && { index: dataViewObj.id }), ...(addColumnsToState && { columns: nextColumns }), }; - stateContainer.replaceUrlAppState(nextState); + stateContainer.appState.replaceUrlState(nextState); } else { // cleanup for a "regular" query cleanup(); diff --git a/src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.test.ts b/src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.test.ts new file mode 100644 index 0000000000000..2ea8275dea013 --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.test.ts @@ -0,0 +1,134 @@ +/* + * Copyright 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 { createBrowserHistory } from 'history'; +import { buildStateSubscribe } from './build_state_subscribe'; +import { savedSearchMock } from '../../../../__mocks__/saved_search'; +import { FetchStatus } from '../../../types'; +import { getDiscoverStateContainer } from '../../services/discover_state'; +import { discoverServiceMock } from '../../../../__mocks__/services'; +import { dataViewComplexMock } from '../../../../__mocks__/data_view_complex'; + +describe('buildStateSubscribe', () => { + const savedSearch = savedSearchMock; + const history = createBrowserHistory(); + const stateContainer = getDiscoverStateContainer({ + savedSearch, + services: discoverServiceMock, + history, + }); + stateContainer.dataState.refetch$.next = jest.fn(); + stateContainer.dataState.reset = jest.fn(); + stateContainer.actions.setDataView = jest.fn(); + stateContainer.actions.loadAndResolveDataView = jest.fn(() => + Promise.resolve({ fallback: false, dataView: dataViewComplexMock }) + ); + + const setState = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should set the data view if the index has changed, but no refetch should be triggered', async () => { + await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + })({ index: dataViewComplexMock.id }); + + expect(stateContainer.actions.setDataView).toHaveBeenCalledWith(dataViewComplexMock); + expect(stateContainer.dataState.reset).toHaveBeenCalled(); + expect(stateContainer.dataState.refetch$.next).not.toHaveBeenCalled(); + expect(setState).toHaveBeenCalled(); + }); + + it('should not call refetch$ if nothing changes', async () => { + await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + })(stateContainer.appState.getState()); + + expect(stateContainer.dataState.refetch$.next).toHaveBeenCalled(); + expect(setState).toHaveBeenCalled(); + }); + + it('should call refetch$ if the chart is hidden', async () => { + await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + })({ hideChart: true }); + + expect(stateContainer.dataState.refetch$.next).toHaveBeenCalled(); + expect(setState).toHaveBeenCalled(); + }); + + it('should call refetch$ if the chart interval has changed', async () => { + await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + })({ interval: 's' }); + + expect(stateContainer.dataState.refetch$.next).toHaveBeenCalled(); + expect(setState).toHaveBeenCalled(); + }); + + it('should call refetch$ if breakdownField has changed', async () => { + await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + })({ breakdownField: '💣' }); + + expect(stateContainer.dataState.refetch$.next).toHaveBeenCalled(); + expect(setState).toHaveBeenCalled(); + }); + + it('should call refetch$ if sort has changed', async () => { + await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + })({ sort: [['field', 'test']] }); + + expect(stateContainer.dataState.refetch$.next).toHaveBeenCalled(); + expect(setState).toHaveBeenCalled(); + }); + + it('should not execute setState function if initialFetchStatus is UNINITIALIZED', async () => { + const stateSubscribeFn = await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + }); + stateContainer.dataState.initialFetchStatus = FetchStatus.UNINITIALIZED; + await stateSubscribeFn({ index: dataViewComplexMock.id }); + + expect(stateContainer.dataState.reset).toHaveBeenCalled(); + expect(setState).not.toHaveBeenCalled(); + }); + it('should not execute setState twice if the identical data view change is propagated twice', async () => { + const stateSubscribeFn = await buildStateSubscribe({ + stateContainer, + savedSearch, + setState, + }); + await stateSubscribeFn({ index: dataViewComplexMock.id }); + + expect(setState).toBeCalledTimes(0); + expect(stateContainer.dataState.reset).toBeCalledTimes(1); + + stateContainer.appState.getPrevious = jest.fn(() => ({ index: dataViewComplexMock.id })); + + await stateSubscribeFn({ index: dataViewComplexMock.id }); + expect(setState).toBeCalledTimes(0); + expect(stateContainer.dataState.reset).toBeCalledTimes(1); + }); +}); diff --git a/src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.ts b/src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.ts new file mode 100644 index 0000000000000..2f923a62a6d72 --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/utils/build_state_subscribe.ts @@ -0,0 +1,83 @@ +/* + * Copyright 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 { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { isEqual } from 'lodash'; +import { DiscoverStateContainer } from '../../services/discover_state'; +import { AppState, isEqualState } from '../../services/discover_app_state_container'; +import { addLog } from '../../../../utils/add_log'; +import { FetchStatus } from '../../../types'; + +/** + * Builds a subscribe function for the AppStateContainer, that is executed when the AppState changes in URL + * or programmatically. It's main purpose is to detect which changes should trigger a refetch of the data. + * @param stateContainer + * @param savedSearch + * @param setState + */ +export const buildStateSubscribe = + ({ + stateContainer, + savedSearch, + setState, + }: { + stateContainer: DiscoverStateContainer; + savedSearch: SavedSearch; + setState: (state: AppState) => void; + }) => + async (nextState: AppState) => { + const prevState = stateContainer.appState.getPrevious(); + if (isEqualState(prevState, nextState)) { + addLog('[appstate] subscribe update ignored due to no changes'); + return; + } + addLog('[appstate] subscribe triggered', nextState); + const { hideChart, interval, breakdownField, sort, index } = + stateContainer.appState.getPrevious(); + // Cast to boolean to avoid false positives when comparing + // undefined and false, which would trigger a refetch + const chartDisplayChanged = Boolean(nextState.hideChart) !== Boolean(hideChart); + const chartIntervalChanged = nextState.interval !== interval; + const breakdownFieldChanged = nextState.breakdownField !== breakdownField; + const docTableSortChanged = !isEqual(nextState.sort, sort); + const dataViewChanged = !isEqual(nextState.index, index); + // NOTE: this is also called when navigating from discover app to context app + if (nextState.index && dataViewChanged) { + const { dataView: nextDataView, fallback } = + await stateContainer.actions.loadAndResolveDataView(nextState.index, savedSearch); + + // If the requested data view is not found, don't try to load it, + // and instead reset the app state to the fallback data view + if (fallback) { + stateContainer.appState.update({ index: nextDataView.id }, true); + return; + } + savedSearch.searchSource.setField('index', nextDataView); + stateContainer.dataState.reset(); + stateContainer.actions.setDataView(nextDataView); + } + + if ( + dataViewChanged && + stateContainer.dataState.initialFetchStatus === FetchStatus.UNINITIALIZED + ) { + // stop execution if given data view has changed, and it's not configured to initially start a search in Discover + return; + } + + if ( + chartDisplayChanged || + chartIntervalChanged || + breakdownFieldChanged || + docTableSortChanged + ) { + addLog('[appstate] subscribe triggers data fetching'); + stateContainer.dataState.refetch$.next(undefined); + } + + setState(nextState); + }; diff --git a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.test.ts b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.test.ts new file mode 100644 index 0000000000000..04afdac829f97 --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.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 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 { changeDataView } from './change_data_view'; +import { savedSearchMock } from '../../../../__mocks__/saved_search'; +import { createBrowserHistory } from 'history'; +import { getDiscoverStateContainer } from '../../services/discover_state'; +import { discoverServiceMock } from '../../../../__mocks__/services'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import { dataViewComplexMock } from '../../../../__mocks__/data_view_complex'; + +const setupTestParams = (dataView: DataView | undefined) => { + const savedSearch = savedSearchMock; + const services = discoverServiceMock; + const history = createBrowserHistory(); + const discoverState = getDiscoverStateContainer({ + savedSearch, + services: discoverServiceMock, + history, + }); + discoverState.internalState.transitions.setDataView(savedSearch.searchSource.getField('index')!); + services.dataViews.get = jest.fn(() => Promise.resolve(dataView as DataView)); + discoverState.appState.update = jest.fn(); + return { services, discoverState, setUrlTracking: jest.fn() }; +}; + +describe('changeDataView', () => { + it('should set the right app state when a valid data view to switch to is given', async () => { + const params = setupTestParams(dataViewComplexMock as DataView); + await changeDataView('data-view-with-various-field-types', params); + expect(params.discoverState.appState.update).toHaveBeenCalledWith({ + columns: ['default_column'], + index: 'data-view-with-various-field-types-id', + sort: [['data', 'desc']], + }); + }); + + it('should not set the app state when an invalid data view to switch to is given', async () => { + const params = setupTestParams(undefined); + await changeDataView('data-view-with-various-field-types', params); + expect(params.discoverState.appState.update).not.toHaveBeenCalled(); + }); +}); diff --git a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts new file mode 100644 index 0000000000000..0ceb3c984a165 --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts @@ -0,0 +1,55 @@ +/* + * Copyright 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 { SortOrder } from '@kbn/saved-search-plugin/public'; +import { DataView } from '@kbn/data-views-plugin/common'; +import { addLog } from '../../../../utils/add_log'; +import { DiscoverServices } from '../../../../build_services'; +import { DiscoverStateContainer } from '../../services/discover_state'; +import { getDataViewAppState } from '../../utils/get_switch_data_view_app_state'; +import { MODIFY_COLUMNS_ON_SWITCH, SORT_DEFAULT_ORDER_SETTING } from '../../../../../common'; + +/** + * Function executed when switching data view in the UI + * @param id + * @param services + * @param discoverState + * @param setUrlTracking + */ +export async function changeDataView( + id: string, + { + services, + discoverState, + setUrlTracking, + }: { + services: DiscoverServices; + discoverState: DiscoverStateContainer; + setUrlTracking: (dataView: DataView) => void; + } +) { + addLog('[ui] changeDataView', { id }); + const { dataViews, uiSettings } = services; + const dataView = discoverState.internalState.getState().dataView; + const state = discoverState.appState.getState(); + const nextDataView = await dataViews.get(id); + if (nextDataView && dataView) { + const nextAppState = getDataViewAppState( + dataView, + nextDataView, + state.columns || [], + (state.sort || []) as SortOrder[], + uiSettings.get(MODIFY_COLUMNS_ON_SWITCH), + uiSettings.get(SORT_DEFAULT_ORDER_SETTING), + state.query + ); + + setUrlTracking(nextDataView); + discoverState.appState.update(nextAppState); + } +} diff --git a/src/plugins/discover/public/application/main/services/discover_app_state_container.test.ts b/src/plugins/discover/public/application/main/services/discover_app_state_container.test.ts new file mode 100644 index 0000000000000..80fb6c241b2f5 --- /dev/null +++ b/src/plugins/discover/public/application/main/services/discover_app_state_container.test.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 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 { createKbnUrlStateStorage, withNotifyOnErrors } from '@kbn/kibana-utils-plugin/public'; +import { History } from 'history'; + +import { savedSearchMock } from '../../../__mocks__/saved_search'; +import { discoverServiceMock } from '../../../__mocks__/services'; +import { + DiscoverAppStateContainer, + getDiscoverAppStateContainer, +} from './discover_app_state_container'; + +let history: History; +let state: DiscoverAppStateContainer; + +describe('Test discover app state container', () => { + beforeEach(async () => { + const storeInSessionStorage = discoverServiceMock.uiSettings.get('state:storeInSessionStorage'); + const toasts = discoverServiceMock.core.notifications.toasts; + const stateStorage = createKbnUrlStateStorage({ + useHash: storeInSessionStorage, + history, + ...(toasts && withNotifyOnErrors(toasts)), + }); + state = getDiscoverAppStateContainer({ + stateStorage, + savedSearch: savedSearchMock, + services: discoverServiceMock, + }); + }); + + test('hasChanged returns whether the current state has changed', async () => { + state.set({ index: 'modified' }); + expect(state.hasChanged()).toBeTruthy(); + state.resetInitialState(); + expect(state.hasChanged()).toBeFalsy(); + }); + + test('getPrevious returns the state before the current', async () => { + state.set({ index: 'first' }); + const stateA = state.getState(); + state.set({ index: 'second' }); + expect(state.getPrevious()).toEqual(stateA); + }); +}); diff --git a/src/plugins/discover/public/application/main/services/discover_app_state_container.ts b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts index 0c1c94f72eb9b..2b30e179a2f67 100644 --- a/src/plugins/discover/public/application/main/services/discover_app_state_container.ts +++ b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts @@ -7,13 +7,72 @@ */ import { + createStateContainer, createStateContainerReactHelpers, ReduxLikeStateContainer, } from '@kbn/kibana-utils-plugin/common'; -import { AggregateQuery, Filter, Query } from '@kbn/es-query'; -import { VIEW_MODE } from '@kbn/saved-search-plugin/public'; +import { + AggregateQuery, + COMPARE_ALL_OPTIONS, + compareFilters, + Filter, + FilterStateStore, + Query, +} from '@kbn/es-query'; +import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public'; +import { IKbnUrlStateStorage, ISyncStateRef, syncState } from '@kbn/kibana-utils-plugin/public'; +import { cloneDeep, isEqual } from 'lodash'; +import { connectToQueryState, syncGlobalQueryStateWithUrl } from '@kbn/data-plugin/public'; +import { DiscoverServices } from '../../../build_services'; +import { addLog } from '../../../utils/add_log'; +import { getValidFilters } from '../../../utils/get_valid_filters'; +import { cleanupUrlState } from '../utils/cleanup_url_state'; +import { getStateDefaults } from '../utils/get_state_defaults'; +import { handleSourceColumnState } from '../../../utils/state_helpers'; import { DiscoverGridSettings } from '../../../components/discover_grid/types'; +export const APP_STATE_URL_KEY = '_a'; +export interface DiscoverAppStateContainer extends ReduxLikeStateContainer { + /** + * Returns the previous state, used for diffing e.g. if fetching new data is necessary + */ + getPrevious: () => AppState; + /** + * Determines if the current state is different from the initial state + */ + hasChanged: () => boolean; + /** + * Initializes the state by the given saved search and starts syncing the state with the URL + * @param currentSavedSearch + */ + initAndSync: (currentSavedSearch: SavedSearch) => () => void; + /** + * Replaces the current state in URL with the given state + * @param newState + * @param merge if true, the given state is merged with the current state + */ + replaceUrlState: (newPartial: AppState, merge?: boolean) => void; + /** + * Resets the state by the given saved search + * @param savedSearch + */ + resetWithSavedSearch: (savedSearch: SavedSearch) => void; + /** + * Resets the current state to the initial state + */ + resetInitialState: () => void; + /** + * Start syncing the state with the URL + */ + syncState: () => ISyncStateRef; + /** + * Updates the state, if replace is true, a history.replace is performed instead of history.push + * @param newPartial + * @param replace + */ + update: (newPartial: AppState, replace?: boolean) => void; +} + export interface AppState { /** * Columns displayed in the table @@ -75,3 +134,208 @@ export interface AppState { export const { Provider: DiscoverAppStateProvider, useSelector: useAppStateSelector } = createStateContainerReactHelpers>(); + +/** + * This is the app state container for Discover main, it's responsible for syncing state with the URL + * @param stateStorage + * @param savedSearch + * @param services + */ +export const getDiscoverAppStateContainer = ({ + stateStorage, + savedSearch, + services, +}: { + stateStorage: IKbnUrlStateStorage; + savedSearch: SavedSearch; + services: DiscoverServices; +}): DiscoverAppStateContainer => { + let previousState: AppState = {}; + let initialState = getInitialState(stateStorage, savedSearch, services); + const appStateContainer = createStateContainer(initialState); + + const enhancedAppContainer = { + ...appStateContainer, + set: (value: AppState | null) => { + if (value) { + previousState = appStateContainer.getState(); + appStateContainer.set(value); + } + }, + }; + + const hasChanged = () => { + return !isEqualState(initialState, appStateContainer.getState()); + }; + + const resetInitialState = () => { + addLog('[appState] reset initial state to the current state'); + initialState = appStateContainer.getState(); + }; + + const replaceUrlState = async (newPartial: AppState = {}, merge = true) => { + addLog('[appState] replaceUrlState', { newPartial, merge }); + const state = merge ? { ...appStateContainer.getState(), ...newPartial } : newPartial; + await stateStorage.set(APP_STATE_URL_KEY, state, { replace: true }); + }; + + const startAppStateUrlSync = () => { + addLog('[appState] startAppStateUrlSync'); + return syncState({ + storageKey: APP_STATE_URL_KEY, + stateContainer: enhancedAppContainer, + stateStorage, + }); + }; + + const initializeAndSync = (currentSavedSearch: SavedSearch) => { + addLog('[appState] initializeAndSync', currentSavedSearch); + const dataView = currentSavedSearch.searchSource.getField('index')!; + if (appStateContainer.getState().index !== dataView.id) { + // used data view is different from the given by url/state which is invalid + setState(appStateContainer, { index: dataView.id }); + } + // sync initial app filters from state to filterManager + const filters = appStateContainer.getState().filters || []; + if (filters) { + services.filterManager.setAppFilters(cloneDeep(filters)); + } + const query = appStateContainer.getState().query; + if (query) { + services.data.query.queryString.setQuery(query); + } + + const stopSyncingQueryAppStateWithStateContainer = connectToQueryState( + services.data.query, + appStateContainer, + { + filters: FilterStateStore.APP_STATE, + query: true, + } + ); + + // syncs `_g` portion of url with query services + const { stop: stopSyncingGlobalStateWithUrl } = syncGlobalQueryStateWithUrl( + services.data.query, + stateStorage + ); + + // some filters may not be valid for this context, so update + // the filter manager with a modified list of valid filters + const currentFilters = services.filterManager.getFilters(); + const validFilters = getValidFilters(dataView, currentFilters); + if (!isEqual(currentFilters, validFilters)) { + services.filterManager.setFilters(validFilters); + } + + const { start, stop } = startAppStateUrlSync(); + + replaceUrlState({}).then(() => { + start(); + }); + + return () => { + stopSyncingQueryAppStateWithStateContainer(); + stopSyncingGlobalStateWithUrl(); + stop(); + }; + }; + + const resetWithSavedSearch = (nextSavedSearch: SavedSearch) => { + addLog('[appState] reset to saved search', { nextSavedSearch }); + const nextAppState = getInitialState(stateStorage, nextSavedSearch, services); + appStateContainer.set(nextAppState); + }; + + const update = (newPartial: AppState, replace = false) => { + addLog('[appState] update', { newPartial, replace }); + if (replace) { + return replaceUrlState(newPartial); + } else { + previousState = { ...appStateContainer.getState() }; + setState(appStateContainer, newPartial); + } + }; + + const getPrevious = () => previousState; + + return { + ...enhancedAppContainer, + getPrevious, + hasChanged, + initAndSync: initializeAndSync, + resetWithSavedSearch, + resetInitialState, + replaceUrlState, + syncState: startAppStateUrlSync, + update, + }; +}; + +export interface AppStateUrl extends Omit { + /** + * Necessary to take care of legacy links [fieldName,direction] + */ + sort?: string[][] | [string, string]; +} + +export const GLOBAL_STATE_URL_KEY = '_g'; + +function getInitialState( + stateStorage: IKbnUrlStateStorage, + savedSearch: SavedSearch, + services: DiscoverServices +) { + const appStateFromUrl = cleanupUrlState(stateStorage.get(APP_STATE_URL_KEY) as AppStateUrl); + const defaultAppState = getStateDefaults({ + savedSearch, + services, + }); + return handleSourceColumnState( + { + ...defaultAppState, + ...appStateFromUrl, + }, + services.uiSettings + ); +} + +/** + * Helper function to merge a given new state with the existing state and to set the given state + * container + */ +export function setState(stateContainer: ReduxLikeStateContainer, newState: AppState) { + addLog('[appstate] setState', { newState }); + const oldState = stateContainer.getState(); + const mergedState = { ...oldState, ...newState }; + if (!isEqualState(oldState, mergedState)) { + stateContainer.set(mergedState); + } +} + +/** + * Helper function to compare 2 different filter states + */ +export function isEqualFilters(filtersA?: Filter[] | Filter, filtersB?: Filter[] | Filter) { + if (!filtersA && !filtersB) { + return true; + } else if (!filtersA || !filtersB) { + return false; + } + return compareFilters(filtersA, filtersB, COMPARE_ALL_OPTIONS); +} + +/** + * Helper function to compare 2 different state, is needed since comparing filters + * works differently + */ +export function isEqualState(stateA: AppState, stateB: AppState) { + if (!stateA && !stateB) { + return true; + } else if (!stateA || !stateB) { + return false; + } + const { filters: stateAFilters = [], ...stateAPartial } = stateA; + const { filters: stateBFilters = [], ...stateBPartial } = stateB; + return isEqual(stateAPartial, stateBPartial) && isEqualFilters(stateAFilters, stateBFilters); +} diff --git a/src/plugins/discover/public/application/main/services/discover_state.test.ts b/src/plugins/discover/public/application/main/services/discover_state.test.ts index f3ed93a3394df..a61808d433b5b 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.test.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.test.ts @@ -18,10 +18,16 @@ import { savedSearchMock, savedSearchMockWithTimeField } from '../../../__mocks_ import { discoverServiceMock } from '../../../__mocks__/services'; import { dataViewMock } from '../../../__mocks__/data_view'; import { dataViewComplexMock } from '../../../__mocks__/data_view_complex'; +import { DiscoverAppStateContainer } from './discover_app_state_container'; let history: History; let state: DiscoverStateContainer; const getCurrentUrl = () => history.createHref(history.location); +const startSync = (appState: DiscoverAppStateContainer) => { + const { start, stop } = appState.syncState(); + start(); + return stop; +}; describe('Test discover state', () => { let stopSync = () => {}; @@ -34,8 +40,8 @@ describe('Test discover state', () => { services: discoverServiceMock, history, }); - await state.replaceUrlAppState({}); - stopSync = state.startSync(); + await state.appState.update({}, true); + stopSync = startSync(state.appState); }); afterEach(() => { stopSync(); @@ -43,7 +49,7 @@ describe('Test discover state', () => { }); test('setting app state and syncing to URL', async () => { state.setAppState({ index: 'modified' }); - state.flushToUrl(); + state.kbnUrlStateStorage.kbnUrlControls.flush(); expect(getCurrentUrl()).toMatchInlineSnapshot( `"/#?_a=(columns:!(default_column),index:modified,interval:auto,sort:!())"` ); @@ -67,16 +73,16 @@ describe('Test discover state', () => { test('isAppStateDirty returns whether the current state has changed', async () => { state.setAppState({ index: 'modified' }); - expect(state.isAppStateDirty()).toBeTruthy(); - state.resetInitialAppState(); - expect(state.isAppStateDirty()).toBeFalsy(); + expect(state.appState.hasChanged()).toBeTruthy(); + state.appState.resetInitialState(); + expect(state.appState.hasChanged()).toBeFalsy(); }); test('getPreviousAppState returns the state before the current', async () => { state.setAppState({ index: 'first' }); const stateA = state.appState.getState(); state.setAppState({ index: 'second' }); - expect(state.getPreviousAppState()).toEqual(stateA); + expect(state.appState.getPrevious()).toEqual(stateA); }); test('pauseAutoRefreshInterval sets refreshInterval.pause to true', async () => { @@ -96,8 +102,8 @@ describe('Test discover initial state sort handling', () => { services: discoverServiceMock, history, }); - await state.replaceUrlAppState({}); - const stopSync = state.startSync(); + await state.appState.update({}, true); + const stopSync = startSync(state.appState); expect(state.appState.getState().sort).toEqual([['order_date', 'desc']]); stopSync(); }); @@ -110,8 +116,8 @@ describe('Test discover initial state sort handling', () => { services: discoverServiceMock, history, }); - await state.replaceUrlAppState({}); - const stopSync = state.startSync(); + await state.appState.update({}, true); + const stopSync = startSync(state.appState); expect(state.appState.getState().sort).toEqual([['bytes', 'desc']]); stopSync(); }); @@ -123,8 +129,8 @@ describe('Test discover initial state sort handling', () => { services: discoverServiceMock, history, }); - await state.replaceUrlAppState({}); - const stopSync = state.startSync(); + await state.appState.update({}, true); + const stopSync = startSync(state.appState); expect(state.appState.getState().sort).toEqual([['timestamp', 'desc']]); stopSync(); }); 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 7a8493c87c1f9..934c599be785f 100644 --- a/src/plugins/discover/public/application/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/main/services/discover_state.ts @@ -6,50 +6,37 @@ * Side Public License, v 1. */ -import { cloneDeep, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; import { History } from 'history'; -import { COMPARE_ALL_OPTIONS, compareFilters, Filter, FilterStateStore } from '@kbn/es-query'; import { createKbnUrlStateStorage, - createStateContainer, IKbnUrlStateStorage, - ReduxLikeStateContainer, StateContainer, - syncState, withNotifyOnErrors, } from '@kbn/kibana-utils-plugin/public'; import { - connectToQueryState, DataPublicPluginStart, FilterManager, QueryState, SearchSessionInfoProvider, - syncQueryStateWithUrl, } from '@kbn/data-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; import { SavedSearch } from '@kbn/saved-search-plugin/public'; +import { loadDataView, resolveDataView } from '../utils/resolve_data_view'; import { DataStateContainer, getDataStateContainer } from './discover_data_state_container'; import { DiscoverSearchSessionManager } from './discover_search_session'; -import { DiscoverAppLocatorParams, DISCOVER_APP_LOCATOR } from '../../../../common'; -import { AppState } from './discover_app_state_container'; +import { DISCOVER_APP_LOCATOR, DiscoverAppLocatorParams } from '../../../../common'; +import { + AppState, + DiscoverAppStateContainer, + getDiscoverAppStateContainer, + GLOBAL_STATE_URL_KEY, +} from './discover_app_state_container'; import { getInternalStateContainer, InternalStateContainer, } from './discover_internal_state_container'; -import { getStateDefaults } from '../utils/get_state_defaults'; import { DiscoverServices } from '../../../build_services'; -import { handleSourceColumnState } from '../../../utils/state_helpers'; -import { cleanupUrlState } from '../utils/cleanup_url_state'; -import { getValidFilters } from '../../../utils/get_valid_filters'; - -export interface AppStateUrl extends Omit { - /** - * Necessary to take care of legacy links [fieldName,direction] - */ - sort?: string[][] | [string, string]; -} - interface DiscoverStateContainerParams { /** * Browser history @@ -73,7 +60,7 @@ export interface DiscoverStateContainer { /** * App state, the _a part of the URL */ - appState: ReduxLikeStateContainer; + appState: DiscoverAppStateContainer; /** * Internal state that's used at several places in the UI */ @@ -94,38 +81,10 @@ export interface DiscoverStateContainer { filterManager: FilterManager, data: DataPublicPluginStart ) => () => void; - /** - * Start sync between state and URL -- only used for testing - */ - startSync: () => () => void; /** * Set app state to with a partial new app state */ setAppState: (newState: Partial) => void; - /** - * Set state in Url using history.replace - */ - replaceUrlAppState: (newState: Partial) => Promise; - /** - * Sync state to URL, used for testing - */ - flushToUrl: () => void; - /** - * Reset initial state to the current app state - */ - resetInitialAppState: () => void; - /** - * Return the Appstate before the current app state, useful for diffing changes - */ - getPreviousAppState: () => AppState; - /** - * Returns whether the current app state is different to the initial state - */ - isAppStateDirty: () => boolean; - /** - * Reset AppState by the given savedSearch discarding all changes - */ - resetAppState: (nextSavedSearch: SavedSearch) => void; /** * Pause the auto refresh interval without pushing an entry to history */ @@ -138,6 +97,17 @@ export interface DiscoverStateContainer { * Set the currently selected data view */ setDataView: (dataView: DataView) => void; + /** + * Load the data view of the given id + * A fallback data view is returned, given there's no match + * This is usually the default data view + * @param dataViewId + * @param savedSearch + */ + loadAndResolveDataView: ( + dataViewId: string, + savedSearch: SavedSearch + ) => Promise<{ fallback: boolean; dataView: DataView }>; /** * Load current list of data views, add them to internal state */ @@ -165,9 +135,6 @@ export interface DiscoverStateContainer { }; } -const APP_STATE_URL_KEY = '_a'; -const GLOBAL_STATE_URL_KEY = '_g'; - /** * Builds and returns appState and globalState containers and helper functions * Used to sync URL with UI state @@ -179,10 +146,6 @@ export function getDiscoverStateContainer({ }: DiscoverStateContainerParams): DiscoverStateContainer { const storeInSessionStorage = services.uiSettings.get('state:storeInSessionStorage'); const toasts = services.core.notifications.toasts; - const defaultAppState = getStateDefaults({ - savedSearch, - services, - }); const stateStorage = createKbnUrlStateStorage({ useHash: storeInSessionStorage, history, @@ -196,48 +159,10 @@ export function getDiscoverStateContainer({ history, session: services.data.search.session, }); - - const appStateFromUrl = cleanupUrlState(stateStorage.get(APP_STATE_URL_KEY) as AppStateUrl); - - let initialAppState = handleSourceColumnState( - { - ...defaultAppState, - ...appStateFromUrl, - }, - services.uiSettings - ); - - // todo filter source depending on fields fetching flag (if no columns remain and source fetching is enabled, use default columns) - let previousAppState: AppState; - const appStateContainer = createStateContainer(initialAppState); - - const appStateContainerModified = { - ...appStateContainer, - set: (value: AppState | null) => { - if (value) { - previousAppState = appStateContainer.getState(); - appStateContainer.set(value); - } - }, - }; - - // Calling syncState from within initializeAndSync causes state syncing issues. - // syncState takes a snapshot of the initial state when it's called to compare - // against before syncing state updates. When syncState is called from outside - // of initializeAndSync, the snapshot doesn't get reset when the data view is - // changed. Then when the user presses the back button, the new state appears - // to be the same as the initial state, so syncState ignores the update. - const syncAppState = () => - syncState({ - storageKey: APP_STATE_URL_KEY, - stateContainer: appStateContainerModified, - stateStorage, - }); - - const replaceUrlAppState = async (newPartial: AppState = {}) => { - const state = { ...appStateContainer.getState(), ...newPartial }; - await stateStorage.set(APP_STATE_URL_KEY, state, { replace: true }); - }; + /** + * App State Container, synced with URL + */ + const appStateContainer = getDiscoverAppStateContainer({ stateStorage, savedSearch, services }); const internalStateContainer = getInternalStateContainer(); @@ -280,89 +205,28 @@ export function getDiscoverStateContainer({ internalStateContainer.transitions.setSavedDataViews(dataViewList); }; + const loadAndResolveDataView = async (id: string, actualSavedSearch: SavedSearch) => { + const nextDataViewData = await loadDataView(services.dataViews, services.uiSettings, id); + const nextDataView = resolveDataView( + nextDataViewData, + actualSavedSearch.searchSource, + services.toastNotifications + ); + return { fallback: !nextDataViewData.stateValFound, dataView: nextDataView }; + }; + return { kbnUrlStateStorage: stateStorage, - appState: appStateContainerModified, + appState: appStateContainer, internalState: internalStateContainer, dataState: dataStateContainer, searchSessionManager, - startSync: () => { - const { start, stop } = syncAppState(); - start(); - return stop; - }, - setAppState: (newPartial: AppState) => setState(appStateContainerModified, newPartial), - replaceUrlAppState, - resetInitialAppState: () => { - initialAppState = appStateContainer.getState(); - }, - resetAppState: (nextSavedSearch: SavedSearch) => { - const defaultState = handleSourceColumnState( - getStateDefaults({ savedSearch: nextSavedSearch, services }), - services.uiSettings - ); - setState(appStateContainerModified, defaultState); - }, - getPreviousAppState: () => previousAppState, - flushToUrl: () => stateStorage.kbnUrlControls.flush(), - isAppStateDirty: () => !isEqualState(initialAppState, appStateContainer.getState()), + setAppState: (newPartial: AppState) => appStateContainer.update(newPartial), pauseAutoRefreshInterval, - initializeAndSync: ( - dataView: DataView, - filterManager: FilterManager, - data: DataPublicPluginStart - ) => { - if (appStateContainer.getState().index !== dataView.id) { - // used data view is different than the given by url/state which is invalid - setState(appStateContainerModified, { index: dataView.id }); - } - // sync initial app filters from state to filterManager - const filters = appStateContainer.getState().filters || []; - if (filters) { - filterManager.setAppFilters(cloneDeep(filters)); - } - const query = appStateContainer.getState().query; - if (query) { - data.query.queryString.setQuery(query); - } - - const stopSyncingQueryAppStateWithStateContainer = connectToQueryState( - data.query, - appStateContainer, - { - filters: FilterStateStore.APP_STATE, - query: true, - } - ); - - // syncs `_g` portion of url with query services - const { stop: stopSyncingGlobalStateWithUrl } = syncQueryStateWithUrl( - data.query, - 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(() => { - start(); - }); - - return () => { - stopSyncingQueryAppStateWithStateContainer(); - stopSyncingGlobalStateWithUrl(); - stop(); - }; - }, + initializeAndSync: () => appStateContainer.initAndSync(savedSearch), actions: { setDataView, + loadAndResolveDataView, loadDataViewList, setAdHocDataViews, appendAdHocDataViews, @@ -372,54 +236,6 @@ export function getDiscoverStateContainer({ }; } -/** - * Helper function to merge a given new state with the existing state and to set the given state - * container - */ -export function setState(stateContainer: ReduxLikeStateContainer, newState: AppState) { - const oldState = stateContainer.getState(); - const mergedState = { ...oldState, ...newState }; - if (!isEqualState(oldState, mergedState)) { - stateContainer.set(mergedState); - } -} - -/** - * Helper function to compare 2 different filter states - */ -export function isEqualFilters(filtersA?: Filter[] | Filter, filtersB?: Filter[] | Filter) { - if (!filtersA && !filtersB) { - return true; - } else if (!filtersA || !filtersB) { - return false; - } - return compareFilters(filtersA, filtersB, COMPARE_ALL_OPTIONS); -} - -/** - * helper function to extract filters of the given state - * returns a state object without filters and an array of filters - */ -export function splitState(state: AppState = {}) { - const { filters = [], ...statePartial } = state; - return { filters, state: statePartial }; -} - -/** - * Helper function to compare 2 different state, is needed since comparing filters - * works differently - */ -export function isEqualState(stateA: AppState, stateB: AppState) { - if (!stateA && !stateB) { - return true; - } else if (!stateA || !stateB) { - return false; - } - const { filters: stateAFilters = [], ...stateAPartial } = stateA; - const { filters: stateBFilters = [], ...stateBPartial } = stateB; - return isEqual(stateAPartial, stateBPartial) && isEqualFilters(stateAFilters, stateBFilters); -} - export function createSearchSessionRestorationDataProvider(deps: { appStateContainer: StateContainer; data: DataPublicPluginStart; diff --git a/src/plugins/discover/public/application/main/utils/cleanup_url_state.test.ts b/src/plugins/discover/public/application/main/utils/cleanup_url_state.test.ts index b00d7720e38b2..ea1af49f48e89 100644 --- a/src/plugins/discover/public/application/main/utils/cleanup_url_state.test.ts +++ b/src/plugins/discover/public/application/main/utils/cleanup_url_state.test.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ +import { AppStateUrl } from '../services/discover_app_state_container'; import { cleanupUrlState } from './cleanup_url_state'; -import { AppStateUrl } from '../services/discover_state'; describe('cleanupUrlState', () => { test('cleaning up legacy sort', async () => { diff --git a/src/plugins/discover/public/application/main/utils/cleanup_url_state.ts b/src/plugins/discover/public/application/main/utils/cleanup_url_state.ts index c0e5e4ed8198b..3dab3ac525d8d 100644 --- a/src/plugins/discover/public/application/main/utils/cleanup_url_state.ts +++ b/src/plugins/discover/public/application/main/utils/cleanup_url_state.ts @@ -6,9 +6,8 @@ * Side Public License, v 1. */ import { isOfAggregateQueryType } from '@kbn/es-query'; -import { AppState } from '../services/discover_app_state_container'; +import { AppState, AppStateUrl } from '../services/discover_app_state_container'; import { migrateLegacyQuery } from '../../../utils/migrate_legacy_query'; -import { AppStateUrl } from '../services/discover_state'; /** * Takes care of the given url state, migrates legacy props and cleans up empty props diff --git a/src/plugins/discover/public/hooks/use_confirm_persistence_prompt.ts b/src/plugins/discover/public/hooks/use_confirm_persistence_prompt.ts index 1f98837a8eb25..d5ea19c4316b3 100644 --- a/src/plugins/discover/public/hooks/use_confirm_persistence_prompt.ts +++ b/src/plugins/discover/public/hooks/use_confirm_persistence_prompt.ts @@ -32,7 +32,7 @@ export const useConfirmPersistencePrompt = (stateContainer: DiscoverStateContain updateFiltersReferences(adHocDataView, persistedDataView); stateContainer.actions.removeAdHocDataViewById(adHocDataView.id!); - await stateContainer.replaceUrlAppState({ index: persistedDataView.id }); + await stateContainer.appState.update({ index: persistedDataView.id }, true); const message = i18n.translate('discover.dataViewPersist.message', { defaultMessage: "Saved '{dataViewName}'", diff --git a/src/plugins/discover/public/utils/add_log.ts b/src/plugins/discover/public/utils/add_log.ts new file mode 100644 index 0000000000000..fd2de53ab4e61 --- /dev/null +++ b/src/plugins/discover/public/utils/add_log.ts @@ -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 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. + */ + +/** + * Conditional (window.ELASTIC_DISCOVER_LOGGER needs to be set to true) logger function + * @param message - mandatory message to log + * @param payload - optional object to log + */ + +export const addLog = (message: string, payload?: unknown) => { + // @ts-expect-error + if (window?.ELASTIC_DISCOVER_LOGGER) { + // eslint-disable-next-line no-console + console.log(`[Discover] ${message}`, payload); + } +}; diff --git a/src/plugins/discover/public/utils/get_sharing_data.ts b/src/plugins/discover/public/utils/get_sharing_data.ts index 9a32a2431649b..d1c07b0c13c6c 100644 --- a/src/plugins/discover/public/utils/get_sharing_data.ts +++ b/src/plugins/discover/public/utils/get_sharing_data.ts @@ -15,14 +15,16 @@ import type { } from '@kbn/data-plugin/public'; import type { Filter } from '@kbn/es-query'; import type { SavedSearch, SortOrder } from '@kbn/saved-search-plugin/public'; -import { AppState } from '../application/main/services/discover_app_state_container'; +import { + AppState, + isEqualFilters, +} from '../application/main/services/discover_app_state_container'; import { getSortForSearchSource } from './sorting'; import { DOC_HIDE_TIME_COLUMN_SETTING, SEARCH_FIELDS_FROM_SOURCE, SORT_DEFAULT_ORDER_SETTING, } from '../../common'; -import { isEqualFilters } from '../application/main/services/discover_state'; /** * Preparing data to share the current state as link or CSV/Report From 8ec4b789884f8d919cae28c15eaf1ceb0f64bc63 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 14 Feb 2023 00:47:16 -0500 Subject: [PATCH 154/203] [api-docs] 2023-02-14 Daily api_docs build (#151096) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/248 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 4 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.devdocs.json | 161 ++++- api_docs/alerting.mdx | 7 +- 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_chat.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.devdocs.json | 51 ++ api_docs/content_management.mdx | 7 +- api_docs/controls.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/ecs_data_quality_dashboard.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/files_management.mdx | 2 +- api_docs/fleet.devdocs.json | 133 +++- api_docs/fleet.mdx | 4 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.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_alerts_ui_shared.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_analytics_shippers_gainsight.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- .../kbn_apm_synthtrace_client.devdocs.json | 6 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.devdocs.json | 36 +- api_docs/kbn_cell_actions.mdx | 4 +- api_docs/kbn_chart_expressions_common.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_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mocks.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 +- .../kbn_content_management_content_editor.mdx | 2 +- .../kbn_content_management_table_list.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_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.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_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.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 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_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 +- ...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_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.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_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_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_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.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 +- ...saved_objects_server_internal.devdocs.json | 44 +- ...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_test_helpers_kbn_server.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.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 | 4 +- .../kbn_core_ui_settings_browser_internal.mdx | 4 +- .../kbn_core_ui_settings_browser_mocks.mdx | 4 +- api_docs/kbn_core_ui_settings_common.mdx | 4 +- api_docs/kbn_core_ui_settings_server.mdx | 4 +- .../kbn_core_ui_settings_server_internal.mdx | 4 +- .../kbn_core_ui_settings_server_mocks.mdx | 4 +- 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_cypress_config.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_ecs.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_es.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_es_types.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 +- .../kbn_ftr_common_functional_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.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_i18n_react.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_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.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_date_picker.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_url_state.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_osquery_io_ts_types.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_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.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 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- ...ared_ux_avatar_user_profile_components.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.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 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_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_prompt_not_found.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_slo_schema.devdocs.json | 10 +- api_docs/kbn_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.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_test_subj_selector.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.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.devdocs.json | 17 +- api_docs/ml.mdx | 4 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.devdocs.json | 12 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 32 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.devdocs.json | 4 +- 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/stack_connectors.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.devdocs.json | 684 +----------------- api_docs/triggers_actions_ui.mdx | 4 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_field_list.mdx | 2 +- api_docs/unified_histogram.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 +- 487 files changed, 929 insertions(+), 1245 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index b9be91ce21ae0..8081780e1ea01 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: 2023-02-13 +date: 2023-02-14 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 2aad7fea352bd..611a57d44acb9 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,14 +8,14 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 5709065f00cef..05dc6e5afd7c2 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: 2023-02-13 +date: 2023-02-14 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 3841ad0358437..0c55e3fbddf4d 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -1711,6 +1711,22 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "alerting", + "id": "def-server.PluginSetupContract.getFrameworkAlertsEnabled", + "type": "Function", + "tags": [], + "label": "getFrameworkAlertsEnabled", + "description": [], + "signature": [ + "() => boolean" + ], + "path": "x-pack/plugins/alerting/server/plugin.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] } ], "initialIsOpen": false @@ -3177,6 +3193,23 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY_NAME", + "type": "string", + "tags": [], + "label": "DEFAULT_ALERTS_ILM_POLICY_NAME", + "description": [ + "\nDefault alert index ILM policy\n- _meta.managed: notify users this is a managed policy and should be modified\n at their own risk\n- no delete phase as we want to keep these indices around indefinitely\n\nThis should be used by all alerts-as-data indices" + ], + "signature": [ + "\".alerts-ilm-policy\"" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-server.DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT", @@ -3648,7 +3681,133 @@ "initialIsOpen": false } ], - "objects": [] + "objects": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY", + "type": "Object", + "tags": [], + "label": "DEFAULT_ALERTS_ILM_POLICY", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy", + "type": "Object", + "tags": [], + "label": "policy", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy._meta", + "type": "Object", + "tags": [], + "label": "_meta", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy._meta.managed", + "type": "boolean", + "tags": [], + "label": "managed", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy.phases", + "type": "Object", + "tags": [], + "label": "phases", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy.phases.hot", + "type": "Object", + "tags": [], + "label": "hot", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy.phases.hot.actions", + "type": "Object", + "tags": [], + "label": "actions", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy.phases.hot.actions.rollover", + "type": "Object", + "tags": [], + "label": "rollover", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy.phases.hot.actions.rollover.max_age", + "type": "string", + "tags": [], + "label": "max_age", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "alerting", + "id": "def-server.DEFAULT_ALERTS_ILM_POLICY.policy.phases.hot.actions.rollover.max_primary_shard_size", + "type": "string", + "tags": [], + "label": "max_primary_shard_size", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/default_lifecycle_policy.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ] + } + ] + } + ] + } + ] + } + ], + "initialIsOpen": false + } + ] }, "common": { "classes": [], diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 375da7aabf00c..3b9b6704f78b0 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 476 | 1 | 466 | 39 | +| 488 | 1 | 477 | 39 | ## Client @@ -36,6 +36,9 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o ## Server +### Objects + + ### Functions diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 2274cfb6f7581..0641e7936a086 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: 2023-02-13 +date: 2023-02-14 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 573a7276b9699..e57536e8708cd 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: 2023-02-13 +date: 2023-02-14 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 ae8d802eb9bb1..85473c285f16b 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: 2023-02-13 +date: 2023-02-14 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 d3c44ad29fbe3..e4fc87e19b294 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: 2023-02-13 +date: 2023-02-14 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 b57d875ca98ff..6d355aa7b186f 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: 2023-02-13 +date: 2023-02-14 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 208035ee0e511..53fc1e7251f0d 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: 2023-02-13 +date: 2023-02-14 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 3dd05b4caa69b..e73ce3a08318f 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_chat.mdx b/api_docs/cloud_chat.mdx index 8348bc64b0c57..11590e43c4849 100644 --- a/api_docs/cloud_chat.mdx +++ b/api_docs/cloud_chat.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudChat title: "cloudChat" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudChat plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudChat'] --- import cloudChatObj from './cloud_chat.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index e59aaa8f4662b..6fe3cbd675fb3 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 4d1771e9abed3..a95b0365b8a74 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index c9ba0c13625b9..947805cae74ee 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 1f26d30425d20..84532c797d8b2 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: 2023-02-13 +date: 2023-02-14 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 1e72619a9d2d3..40c95cb431afd 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.devdocs.json b/api_docs/content_management.devdocs.json index e745837e88bc3..cd44c8835e205 100644 --- a/api_docs/content_management.devdocs.json +++ b/api_docs/content_management.devdocs.json @@ -31,10 +31,61 @@ "path": "src/plugins/content_management/public/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentManagementPublicStart.registry", + "type": "Object", + "tags": [], + "label": "registry", + "description": [], + "signature": [ + "{ get: (id: string) => ", + "ContentType", + " | undefined; getAll: () => ", + "ContentType", + "[]; }" + ], + "path": "src/plugins/content_management/public/types.ts", + "deprecated": false, + "trackAdoption": false } ], "lifecycle": "start", "initialIsOpen": true + }, + "setup": { + "parentPluginId": "contentManagement", + "id": "def-public.ContentManagementPublicSetup", + "type": "Interface", + "tags": [], + "label": "ContentManagementPublicSetup", + "description": [], + "path": "src/plugins/content_management/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentManagementPublicSetup.registry", + "type": "Object", + "tags": [], + "label": "registry", + "description": [], + "signature": [ + "{ register: (definition: ", + "ContentTypeDefinition", + ") => ", + "ContentType", + "; }" + ], + "path": "src/plugins/content_management/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "setup", + "initialIsOpen": true } }, "server": { diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 4d2b9e6e5351d..ac9a30392db92 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 22 | 0 | 22 | 1 | +| 25 | 0 | 25 | 3 | ## Client +### Setup + + ### Start diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 71cd2e5f65cd4..67cd5ac67afc5 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index 8bdd11f8b69b1..508a37683a8e1 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: 2023-02-13 +date: 2023-02-14 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 6e387484de43f..c51b0138a8dd8 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: 2023-02-13 +date: 2023-02-14 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 09a6d90b76b84..068e3153c3381 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: 2023-02-13 +date: 2023-02-14 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 190d0276f2e2d..03a33ea3ad687 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: 2023-02-13 +date: 2023-02-14 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 ab079f19bf2d2..917b2f1450b3d 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: 2023-02-13 +date: 2023-02-14 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 bbb7a415a99e1..cc0012f6531e6 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: 2023-02-13 +date: 2023-02-14 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 cf8efde83624e..c24951b3827a6 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: 2023-02-13 +date: 2023-02-14 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 6e12552b4a433..7e1f931c115ce 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: 2023-02-13 +date: 2023-02-14 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 c4a0c8822f005..b611bafdd9e64 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: 2023-02-13 +date: 2023-02-14 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 e6492a967fb77..eb42fba4b9ee4 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: 2023-02-13 +date: 2023-02-14 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 8381a91277964..ec3b494223104 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: 2023-02-13 +date: 2023-02-14 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 37268da64d6fa..090f291a24f24 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 4bcdb9a901e1f..eabbfad5bed79 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 50f8afa08c804..997514f33bf72 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 41d539f12123a..d4d6f60e325b6 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: 2023-02-13 +date: 2023-02-14 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 7ae9672c44932..8eb7c1066e9a6 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: 2023-02-13 +date: 2023-02-14 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 10b4c487e8fd6..29889770155dd 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 8ab9a88d3a593..35d7f74611338 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index a42c12b9cf58d..1ebab619b4a63 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: 2023-02-13 +date: 2023-02-14 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 28e675627e8ef..a1630d4a1da7d 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: 2023-02-13 +date: 2023-02-14 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 1b99d881f3521..3b9785ee471b3 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: 2023-02-13 +date: 2023-02-14 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 0415fed328382..a82ccaf660608 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: 2023-02-13 +date: 2023-02-14 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 434c2bd5ea789..90a3577de3850 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: 2023-02-13 +date: 2023-02-14 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 b7b0b6b76eb4f..d164db625637a 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: 2023-02-13 +date: 2023-02-14 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 166b99f16fcab..d2270b0d3220f 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: 2023-02-13 +date: 2023-02-14 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 06e9cec3bc982..d9afef81e5883 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: 2023-02-13 +date: 2023-02-14 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 c8d1013f8c1de..d653c57a7cc0d 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: 2023-02-13 +date: 2023-02-14 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 cd9983cefeb37..203f42c0e0dc2 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: 2023-02-13 +date: 2023-02-14 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 6602fc473f8b1..137d86ba74560 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: 2023-02-13 +date: 2023-02-14 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 4d812d11b4bfc..2b036b95e4706 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: 2023-02-13 +date: 2023-02-14 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 a8ba54652620f..5ccbe20ce0df5 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: 2023-02-13 +date: 2023-02-14 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 7fd4da9966fd9..107f0ba246043 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: 2023-02-13 +date: 2023-02-14 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 64c80e93089f1..5978e57d2c543 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: 2023-02-13 +date: 2023-02-14 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 7a6ad29dfc08e..096b2e79b235d 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: 2023-02-13 +date: 2023-02-14 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 51d9a7b54a37c..28b2429a71aae 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: 2023-02-13 +date: 2023-02-14 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 ad67465521184..b966fb8190dae 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: 2023-02-13 +date: 2023-02-14 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 af19b56f0b273..692ecd0d33d8a 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: 2023-02-13 +date: 2023-02-14 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 122fce6eb9c20..0e9067daa9910 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: 2023-02-13 +date: 2023-02-14 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 fdf04289d9dc1..f22be28c06862 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: 2023-02-13 +date: 2023-02-14 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 c7cf28c806c03..9acfd8cc9ecf3 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: 2023-02-13 +date: 2023-02-14 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 ec7a134ceda16..fff83c3c4e308 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: 2023-02-13 +date: 2023-02-14 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 57c4d6a70bdb4..dee0043b492e5 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: 2023-02-13 +date: 2023-02-14 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 14ccd3730ff42..d22bbb90e6eaa 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 792cafaeee9b5..36e1399bb18d4 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index 1a95d073f190b..eb4d759b19836 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -5470,6 +5470,100 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-server.MessageSigningServiceInterface", + "type": "Interface", + "tags": [], + "label": "MessageSigningServiceInterface", + "description": [], + "path": "x-pack/plugins/fleet/server/services/security/message_signing_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.MessageSigningServiceInterface.generateKeyPair", + "type": "Function", + "tags": [], + "label": "generateKeyPair", + "description": [], + "signature": [ + "(providedPassphrase?: string | undefined) => Promise" + ], + "path": "x-pack/plugins/fleet/server/services/security/message_signing_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.MessageSigningServiceInterface.generateKeyPair.$1", + "type": "string", + "tags": [], + "label": "providedPassphrase", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/security/message_signing_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-server.MessageSigningServiceInterface.sign", + "type": "Function", + "tags": [], + "label": "sign", + "description": [], + "signature": [ + "(serializedMessage: object | Buffer) => Promise<{ data: Buffer; signature: string; }>" + ], + "path": "x-pack/plugins/fleet/server/services/security/message_signing_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.MessageSigningServiceInterface.sign.$1", + "type": "CompoundType", + "tags": [], + "label": "serializedMessage", + "description": [], + "signature": [ + "object | Buffer" + ], + "path": "x-pack/plugins/fleet/server/services/security/message_signing_service.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-server.MessageSigningServiceInterface.getPublicKey", + "type": "Function", + "tags": [], + "label": "getPublicKey", + "description": [], + "signature": [ + "() => Promise" + ], + "path": "x-pack/plugins/fleet/server/services/security/message_signing_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-server.PackageClient", @@ -15630,6 +15724,26 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "fleet", + "id": "def-server.FleetStartContract.messageSigningService", + "type": "Object", + "tags": [], + "label": "messageSigningService", + "description": [], + "signature": [ + { + "pluginId": "fleet", + "scope": "server", + "docId": "kibFleetPluginApi", + "section": "def-server.MessageSigningServiceInterface", + "text": "MessageSigningServiceInterface" + } + ], + "path": "x-pack/plugins/fleet/server/plugin.ts", + "deprecated": false, + "trackAdoption": false } ], "lifecycle": "start", @@ -22357,7 +22471,7 @@ "label": "FleetServerAgentComponentStatus", "description": [], "signature": [ - "\"failed\" | \"degraded\" | \"starting\" | \"configuring\" | \"healthy\" | \"stopping\" | \"stopped\"" + "\"STARTING\" | \"CONFIGURING\" | \"HEALTHY\" | \"DEGRADED\" | \"FAILED\" | \"STOPPING\" | \"STOPPED\"" ], "path": "x-pack/plugins/fleet/common/types/models/agent.ts", "deprecated": false, @@ -22831,6 +22945,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "fleet", + "id": "def-common.MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE", + "type": "string", + "tags": [], + "label": "MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE", + "description": [], + "signature": [ + "\"fleet-message-signing-keys\"" + ], + "path": "x-pack/plugins/fleet/common/constants/message_signing_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "fleet", "id": "def-common.NotInstalled", @@ -25206,7 +25335,7 @@ "label": "FleetServerAgentComponentStatuses", "description": [], "signature": [ - "readonly [\"starting\", \"configuring\", \"healthy\", \"degraded\", \"failed\", \"stopping\", \"stopped\"]" + "readonly [\"STARTING\", \"CONFIGURING\", \"HEALTHY\", \"DEGRADED\", \"FAILED\", \"STOPPING\", \"STOPPED\"]" ], "path": "x-pack/plugins/fleet/common/constants/agent.ts", "deprecated": false, diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index a1e6bfd8c7afc..19e6e335302a4 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 1069 | 3 | 964 | 26 | +| 1077 | 3 | 972 | 26 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 905c4673901c1..f9387f3710982 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index ad0f929239339..e171196eba9a5 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 6284487517edb..34b8bfcf3e713 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 5749a8873dffb..c29b43cc59858 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index 1152691ad7e2a..0205ba667c08c 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: 2023-02-13 +date: 2023-02-14 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 e719e5935fa94..683632756e207 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: 2023-02-13 +date: 2023-02-14 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 5ee14e5b98344..838e6ef53036e 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: 2023-02-13 +date: 2023-02-14 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 a7a08e977cbee..413e04890be52 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: 2023-02-13 +date: 2023-02-14 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 991447d3f14bf..185cf6d189225 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: 2023-02-13 +date: 2023-02-14 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 64a742a86b13e..64eed79df29ad 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: 2023-02-13 +date: 2023-02-14 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 76e6fdd21d06a..a01ad3e755805 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: 2023-02-13 +date: 2023-02-14 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 3d416f3e7adad..5233c4b69a34c 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: 2023-02-13 +date: 2023-02-14 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 d16cee6987121..b44fa5e1dea4a 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index f4e37973e7945..f6c1aa15d515e 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 45f1e8636073c..5553996ae1044 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: 2023-02-13 +date: 2023-02-14 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 17ce8a3a75c3a..58c7f1e508c7e 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: 2023-02-13 +date: 2023-02-14 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 026ca948a937c..63f8e6cd196cf 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: 2023-02-13 +date: 2023-02-14 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 a2c5c4aed4090..25a273427412f 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: 2023-02-13 +date: 2023-02-14 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 f97c7500ae697..f999730a845b6 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: 2023-02-13 +date: 2023-02-14 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 c6a5d84adf8fa..375a243bda7fd 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_gainsight.mdx b/api_docs/kbn_analytics_shippers_gainsight.mdx index 88c4a26d520e1..849801c0b813b 100644 --- a/api_docs/kbn_analytics_shippers_gainsight.mdx +++ b/api_docs/kbn_analytics_shippers_gainsight.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-gainsight title: "@kbn/analytics-shippers-gainsight" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-gainsight plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-gainsight'] --- import kbnAnalyticsShippersGainsightObj from './kbn_analytics_shippers_gainsight.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index cf5438c67ca4c..a314f43892c4f 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: 2023-02-13 +date: 2023-02-14 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 291ddaf5f2b86..4170ff5d5a81a 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.devdocs.json b/api_docs/kbn_apm_synthtrace_client.devdocs.json index 73dc27fa40f91..ea59a115a467f 100644 --- a/api_docs/kbn_apm_synthtrace_client.devdocs.json +++ b/api_docs/kbn_apm_synthtrace_client.devdocs.json @@ -1892,7 +1892,7 @@ "label": "timerange", "description": [], "signature": [ - "(from: number | Date | moment.Moment, to: number | Date | moment.Moment) => ", + "(from: DateLike, to: DateLike) => ", { "pluginId": "@kbn/apm-synthtrace-client", "scope": "common", @@ -1913,7 +1913,7 @@ "label": "from", "description": [], "signature": [ - "number | Date | moment.Moment" + "DateLike" ], "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", "deprecated": false, @@ -1928,7 +1928,7 @@ "label": "to", "description": [], "signature": [ - "number | Date | moment.Moment" + "DateLike" ], "path": "packages/kbn-apm-synthtrace-client/src/lib/timerange.ts", "deprecated": false, diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 02cabdd7fc373..bd37b0ea4f67c 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index ea0f36189cff5..2b2f89f705b2d 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: 2023-02-13 +date: 2023-02-14 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 c26f6d441476b..249169e37641e 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index e1f07f443dc33..b89919c364138 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.devdocs.json b/api_docs/kbn_cell_actions.devdocs.json index 60b3a153b6639..4d6a0fd76d2d5 100644 --- a/api_docs/kbn_cell_actions.devdocs.json +++ b/api_docs/kbn_cell_actions.devdocs.json @@ -101,7 +101,7 @@ "label": "useDataGridColumnsCellActions", "description": [], "signature": [ - "({ fields, triggerId, metadata, disabledActions, }: ", + "({ fields, triggerId, metadata, dataGridRef, disabledActions, }: ", { "pluginId": "@kbn/cell-actions", "scope": "common", @@ -122,7 +122,7 @@ "id": "def-common.useDataGridColumnsCellActions.$1", "type": "Object", "tags": [], - "label": "{\n fields,\n triggerId,\n metadata,\n disabledActions = [],\n}", + "label": "{\n fields,\n triggerId,\n metadata,\n dataGridRef,\n disabledActions = [],\n}", "description": [], "signature": [ { @@ -332,22 +332,6 @@ "deprecated": false, "trackAdoption": false }, - { - "parentPluginId": "@kbn/cell-actions", - "id": "def-common.CellActionExecutionContext.extraContentNodeRef", - "type": "Object", - "tags": [], - "label": "extraContentNodeRef", - "description": [ - "\nRef to a DOM node where the action can add custom HTML." - ], - "signature": [ - "React.MutableRefObject" - ], - "path": "packages/kbn-cell-actions/src/types.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "@kbn/cell-actions", "id": "def-common.CellActionExecutionContext.nodeRef", @@ -419,6 +403,22 @@ "path": "packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/cell-actions", + "id": "def-common.UseDataGridColumnsCellActionsProps.dataGridRef", + "type": "Object", + "tags": [], + "label": "dataGridRef", + "description": [], + "signature": [ + "React.MutableRefObject<", + "EuiDataGridRefProps", + " | null>" + ], + "path": "packages/kbn-cell-actions/src/hooks/use_data_grid_column_cell_actions.tsx", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 51582d43a448a..f79248b133ccc 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-threat-hunting-explore](https://github.com/orgs/elast | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 20 | 0 | 14 | 3 | +| 20 | 0 | 15 | 3 | ## Common diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 1702efaaa3cc0..9c4a57148402b 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index ed0c1570a7a62..5802355864cf3 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: 2023-02-13 +date: 2023-02-14 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 31464a88598e1..028f213b0a1bd 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: 2023-02-13 +date: 2023-02-14 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 1ead9fc172d5c..f0ad8a7c63844 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: 2023-02-13 +date: 2023-02-14 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 d5e2460a36e5f..1dbf374da6d2c 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: 2023-02-13 +date: 2023-02-14 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 f81eb5b015106..e7abbd3a02a4f 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index 49fcd04616f61..6e87faef86a47 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mocks.mdx b/api_docs/kbn_code_editor_mocks.mdx index 6cc31f555196f..91ef416b041b8 100644 --- a/api_docs/kbn_code_editor_mocks.mdx +++ b/api_docs/kbn_code_editor_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mocks title: "@kbn/code-editor-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 456df6361506d..6de0dea97e67c 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: 2023-02-13 +date: 2023-02-14 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 cd9e09fb2a3b9..aef1b36dd6676 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: 2023-02-13 +date: 2023-02-14 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 4aa975df02e1e..c54960fc5824f 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: 2023-02-13 +date: 2023-02-14 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 c668492d6241f..0b826b6527ab1 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index d9be82f46386f..86df584f6447f 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list.mdx b/api_docs/kbn_content_management_table_list.mdx index afdcd894c491e..9d838570f51bd 100644 --- a/api_docs/kbn_content_management_table_list.mdx +++ b/api_docs/kbn_content_management_table_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list title: "@kbn/content-management-table-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list'] --- import kbnContentManagementTableListObj from './kbn_content_management_table_list.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 591a368e29051..64c3f200d0406 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: 2023-02-13 +date: 2023-02-14 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 14deacecb4c32..2b848e7a033dd 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: 2023-02-13 +date: 2023-02-14 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 62b8135649c4e..99d3913bff3dc 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: 2023-02-13 +date: 2023-02-14 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 1b1edb3251960..ed8382ce3e1b7 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: 2023-02-13 +date: 2023-02-14 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 e340db4e7f5bb..00d69d961c985 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: 2023-02-13 +date: 2023-02-14 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 1be403c6b4597..e6186c1ba764e 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: 2023-02-13 +date: 2023-02-14 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 f83439d5eb902..689cbcf625489 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: 2023-02-13 +date: 2023-02-14 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 1dfbf14f847cf..2270d177f9a49 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: 2023-02-13 +date: 2023-02-14 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 1cde78fae358a..755c5b0b15409 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: 2023-02-13 +date: 2023-02-14 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 53b4331aa5e18..d05e438c5bb9e 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: 2023-02-13 +date: 2023-02-14 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_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index ddcab0894c486..8378b7e127a45 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index c135a057c97bc..1f55e187b6304 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 0dc95b9f29d11..27cc4c35835fb 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 487d2796b3453..ac01dbdae8015 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: 2023-02-13 +date: 2023-02-14 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 02b331420427f..1881387f677da 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: 2023-02-13 +date: 2023-02-14 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 9b6f503f6bb42..e34a6a0beb8ac 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: 2023-02-13 +date: 2023-02-14 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 ef74a650c5f19..15a02c4b9d8bd 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: 2023-02-13 +date: 2023-02-14 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 9ce3a7cc45195..d235d833c8535 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: 2023-02-13 +date: 2023-02-14 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 4355357f1a0cb..d7bcf3633241f 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: 2023-02-13 +date: 2023-02-14 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 cfb6264ba1107..56b1e0ed347a4 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: 2023-02-13 +date: 2023-02-14 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 4212631ed672a..e0a1e9fe60df0 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: 2023-02-13 +date: 2023-02-14 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 401d6435d6882..a0ba226cc4453 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: 2023-02-13 +date: 2023-02-14 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 f1cd7b3907cd9..7689c8f461a1e 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: 2023-02-13 +date: 2023-02-14 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 ced5e9431d344..484997ad7be6c 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: 2023-02-13 +date: 2023-02-14 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_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index 3aa260c5a1727..f7bb72ef4788e 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index 899144dfc8a5f..29df58b9b60d3 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index 2ac6be9f87d41..70c9abd7b86d4 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index 33b8c42f4f4f3..18d5262e93e18 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 1048717f2c677..ccbf88e522574 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index efbbfb42370d2..28e288b491d47 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index 9e0057d919719..f3f60910d5e49 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index 0e74a2626206c..dfa339f6c8d06 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: 2023-02-13 +date: 2023-02-14 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 5142aa3a507ac..1ddcfdc1c824c 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: 2023-02-13 +date: 2023-02-14 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 c93c1d05ecf81..95948aaa4b578 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: 2023-02-13 +date: 2023-02-14 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 19d2fed2812e5..5ced53014383c 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: 2023-02-13 +date: 2023-02-14 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 711cca96375e0..769dcb7b2c8c4 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: 2023-02-13 +date: 2023-02-14 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 3782a3a2f2ab7..d59192b270317 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: 2023-02-13 +date: 2023-02-14 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 106bea0abaddf..4d332f34e6b3e 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: 2023-02-13 +date: 2023-02-14 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 db14485f7a21a..1abaa0f0eafe9 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: 2023-02-13 +date: 2023-02-14 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 5071631cf2f17..c69d188197028 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: 2023-02-13 +date: 2023-02-14 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 9fb36df949fe4..e884c6cbd149e 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: 2023-02-13 +date: 2023-02-14 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 d91c8ef6fbcc9..f09c5b6c51875 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: 2023-02-13 +date: 2023-02-14 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 5a81a0ed08442..7e66da8111069 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: 2023-02-13 +date: 2023-02-14 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 2370318830682..e2f268e77aa95 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: 2023-02-13 +date: 2023-02-14 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 83a609cb286b1..f1f521a4766d3 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: 2023-02-13 +date: 2023-02-14 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 8285d654c2457..dcf999932ba0f 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: 2023-02-13 +date: 2023-02-14 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 cbc198117529b..c82de0ee47105 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: 2023-02-13 +date: 2023-02-14 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 ac8510ebf64a3..2d396ce3130ac 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: 2023-02-13 +date: 2023-02-14 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 b0dc8036d406e..bd7d91d090a2c 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: 2023-02-13 +date: 2023-02-14 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 28974492f3fc4..ec82e2ce7684c 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: 2023-02-13 +date: 2023-02-14 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 c0eb0111c76ca..614d4b9578c9a 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: 2023-02-13 +date: 2023-02-14 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 08e5734096897..0c59dcfffd147 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: 2023-02-13 +date: 2023-02-14 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 a0e10bcdeaf96..7161f62f3686b 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: 2023-02-13 +date: 2023-02-14 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 b098042680c50..d167d912f76a8 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: 2023-02-13 +date: 2023-02-14 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 122d14760368f..09c7f28d30734 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: 2023-02-13 +date: 2023-02-14 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 a748755f6713d..5195bb4cf60b5 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: 2023-02-13 +date: 2023-02-14 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 7bbc2f221deaa..7ddd858b3139d 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: 2023-02-13 +date: 2023-02-14 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 74c01aa514e21..869afff29a1f6 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: 2023-02-13 +date: 2023-02-14 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 28f7097f8ad73..4016d613c0ed5 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: 2023-02-13 +date: 2023-02-14 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 687b92558e613..b3dc059843371 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: 2023-02-13 +date: 2023-02-14 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 b2135ed5b6219..15546280018fb 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: 2023-02-13 +date: 2023-02-14 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 000deefbf8e0b..7ddc5b61bc571 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: 2023-02-13 +date: 2023-02-14 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 455bb6d024f93..079beb348182c 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: 2023-02-13 +date: 2023-02-14 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_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 5648e9c6de077..e1f2f81b91be0 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index 2d999eda8f05f..eda6e1a306b37 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index b27c32bdd02c8..06a0bd69afbac 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index 701f651dc888b..7bdfd693df6f8 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_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 a51d636f675d2..376722151aea5 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: 2023-02-13 +date: 2023-02-14 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 961663af494d8..9ab455696f013 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: 2023-02-13 +date: 2023-02-14 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 00bc4e7585949..31a2106f9cd50 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: 2023-02-13 +date: 2023-02-14 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 1a0a96d63c7b1..ab52e8940cf0f 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: 2023-02-13 +date: 2023-02-14 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 cc704b8f02f84..4a9e7912302c7 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: 2023-02-13 +date: 2023-02-14 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 61bce5767465d..50e9f3bb2fb76 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: 2023-02-13 +date: 2023-02-14 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 daf3cefc4df6e..ae05fed929b2c 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: 2023-02-13 +date: 2023-02-14 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 446f3a0574c61..8ea77d81030a4 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: 2023-02-13 +date: 2023-02-14 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 b733326b6280d..2a1d4291be589 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: 2023-02-13 +date: 2023-02-14 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 55f063983fb98..c233ab6394da3 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: 2023-02-13 +date: 2023-02-14 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_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 2638692eb440b..5609f1213e3ab 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: 2023-02-13 +date: 2023-02-14 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 73960cf9d8992..fa7f995b4278e 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: 2023-02-13 +date: 2023-02-14 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 2a67cbc81cb59..ff7539fddae93 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: 2023-02-13 +date: 2023-02-14 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_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 558fa7aad1707..e355a48b1ba2f 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index 0b76f6e30963e..0a32a81aadc9f 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index 4c9eb53377958..5a154132836e7 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index 2080026784a37..15ed314ea6d5e 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 463b730063e3e..ee10a4fb0a698 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 28486fecbb7a2..7ba0e5d2d9293 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 1f6587b96ba29..4983258f5d6fa 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: 2023-02-13 +date: 2023-02-14 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 f4c9c22ca1194..433721cda5e56 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: 2023-02-13 +date: 2023-02-14 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 41ca1172ecabe..e1ae4a76ae7e4 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: 2023-02-13 +date: 2023-02-14 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 b0470f4d21d82..e906716c410f5 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: 2023-02-13 +date: 2023-02-14 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 e610ff8c17fdd..11cc8e6f3ef23 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: 2023-02-13 +date: 2023-02-14 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 1c7fbbdb11e18..6622df8657c3a 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: 2023-02-13 +date: 2023-02-14 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 e306b1e55b3c9..8bc2b96935113 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: 2023-02-13 +date: 2023-02-14 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 0c28f0ae37ff2..3190e483476e2 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: 2023-02-13 +date: 2023-02-14 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 31baac187b00c..efbdbc165152b 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: 2023-02-13 +date: 2023-02-14 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 941d30019470a..042777b14f3d8 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: 2023-02-13 +date: 2023-02-14 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 90b1aa8fceb02..3a8acb66e5eed 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: 2023-02-13 +date: 2023-02-14 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 12dbd00dabdbf..9b3e259bdcfb8 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: 2023-02-13 +date: 2023-02-14 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 af87e4732a5ca..c035aa8c428a0 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: 2023-02-13 +date: 2023-02-14 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 7908493e3bd84..710a431de4844 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: 2023-02-13 +date: 2023-02-14 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 23d5e24a71dbd..1f16890da3e6e 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: 2023-02-13 +date: 2023-02-14 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 49841dce2cf5b..6dd80d136a615 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: 2023-02-13 +date: 2023-02-14 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 5a80429b2c356..6dae73c122945 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: 2023-02-13 +date: 2023-02-14 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 c12d0ceb9e475..589cb8c4b966b 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: 2023-02-13 +date: 2023-02-14 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_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 8df2e2c56f68b..9744ba19de107 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 5cbd47140e5f9..4e5e085743680 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index dc1412daabfa3..4ed6cd0f77b93 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 96a2824bb4c10..f681a766b1679 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index b296c61e4b55d..d14dca6b061f9 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: 2023-02-13 +date: 2023-02-14 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 21887f2b0ce00..b523a30efd0a1 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: 2023-02-13 +date: 2023-02-14 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 6d290cc27d103..35bc993c7877b 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: 2023-02-13 +date: 2023-02-14 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_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index 598972fe50f57..1281d2dd8b2f9 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index 631dcb4e6a58c..4dc81cf57fab1 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index f1855def884c1..ee71b45683757 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.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 38d0fa2530610..a9e5d49cf6839 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: 2023-02-13 +date: 2023-02-14 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 dccc1db9033f5..b3f41ff7de158 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: 2023-02-13 +date: 2023-02-14 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 6cb17b31aa71a..cbabb9eb4b8eb 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: 2023-02-13 +date: 2023-02-14 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 6682dbccbc9a4..160af4631b2ee 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: 2023-02-13 +date: 2023-02-14 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 b18ebe9715ad5..bf86ba55282bb 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: 2023-02-13 +date: 2023-02-14 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 813c7a72804d4..bbbd61653e09c 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: 2023-02-13 +date: 2023-02-14 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 37d9a323ef48c..5168d3bc36761 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: 2023-02-13 +date: 2023-02-14 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 9fbf5c4e2f0b5..21214ea509bcb 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: 2023-02-13 +date: 2023-02-14 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 d516398c4e614..9b188e133e6d3 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: 2023-02-13 +date: 2023-02-14 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 aa5a5c71f6f07..592a9754547ba 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: 2023-02-13 +date: 2023-02-14 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 fce451a8ed782..aa68d1469d7f5 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: 2023-02-13 +date: 2023-02-14 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 2709a7ec38121..5d00445df76ab 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: 2023-02-13 +date: 2023-02-14 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 31c26875fac90..8a708fbcd0bcb 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: 2023-02-13 +date: 2023-02-14 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 5c5b2138835a0..f4d178d7669ec 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: 2023-02-13 +date: 2023-02-14 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 fc19e8a2c3c78..cd3a80264de0d 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: 2023-02-13 +date: 2023-02-14 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.devdocs.json b/api_docs/kbn_core_saved_objects_server_internal.devdocs.json index 7be7397a6d77f..9c40e61589f76 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_server_internal.devdocs.json @@ -192,7 +192,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_create.ts", "deprecated": false, @@ -218,7 +218,7 @@ "id": "def-common.registerBulkCreateRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -242,7 +242,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_delete.ts", "deprecated": false, @@ -268,7 +268,7 @@ "id": "def-common.registerBulkDeleteRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -292,7 +292,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_get.ts", "deprecated": false, @@ -318,7 +318,7 @@ "id": "def-common.registerBulkGetRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -342,7 +342,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_resolve.ts", "deprecated": false, @@ -368,7 +368,7 @@ "id": "def-common.registerBulkResolveRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -392,7 +392,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/bulk_update.ts", "deprecated": false, @@ -418,7 +418,7 @@ "id": "def-common.registerBulkUpdateRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -442,7 +442,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/create.ts", "deprecated": false, @@ -468,7 +468,7 @@ "id": "def-common.registerCreateRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -492,7 +492,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/delete.ts", "deprecated": false, @@ -518,7 +518,7 @@ "id": "def-common.registerDeleteRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -642,7 +642,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/find.ts", "deprecated": false, @@ -668,7 +668,7 @@ "id": "def-common.registerFindRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -692,7 +692,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/get.ts", "deprecated": false, @@ -718,7 +718,7 @@ "id": "def-common.registerGetRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -1102,7 +1102,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/resolve.ts", "deprecated": false, @@ -1128,7 +1128,7 @@ "id": "def-common.registerResolveRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" @@ -1152,7 +1152,7 @@ "signature": [ "(router: ", "InternalSavedObjectRouter", - ", { coreUsageData }: RouteDependencies) => void" + ", { coreUsageData, logger }: RouteDependencies) => void" ], "path": "packages/core/saved-objects/core-saved-objects-server-internal/src/routes/update.ts", "deprecated": false, @@ -1178,7 +1178,7 @@ "id": "def-common.registerUpdateRoute.$2", "type": "Object", "tags": [], - "label": "{ coreUsageData }", + "label": "{ coreUsageData, logger }", "description": [], "signature": [ "RouteDependencies" diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index fa39dd6643992..ad614ec070e20 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: 2023-02-13 +date: 2023-02-14 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 c9da4e7dbeef7..8a20b14d0fbb1 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: 2023-02-13 +date: 2023-02-14 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 91a54063e7292..19709fb7bd773 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: 2023-02-13 +date: 2023-02-14 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 56270b61a9e2c..3760a4b4864cd 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: 2023-02-13 +date: 2023-02-14 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 20c7da9de04af..fab984bef7f85 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: 2023-02-13 +date: 2023-02-14 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 705cbac300b07..0d6c40d2ba911 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: 2023-02-13 +date: 2023-02-14 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 935b60790e65a..e14da38f7d072 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: 2023-02-13 +date: 2023-02-14 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 37a8075002b5e..7d6aa936a5fb1 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: 2023-02-13 +date: 2023-02-14 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 8b6361fc33338..e0ebd85e36175 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: 2023-02-13 +date: 2023-02-14 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 bfedd0af8d072..44a91a2e6f156 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: 2023-02-13 +date: 2023-02-14 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_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index cbc60f3076e47..e5a6a6f1e3dbc 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index 735f7a9f60434..27b7e3b9e8a09 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index 8300daab11e48..dee077b4565c4 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 7b5e1a1395bd6..7fd5317aabe0e 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: 2023-02-13 +date: 2023-02-14 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 254ae7ef1a96f..bfd8b5f77afd5 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: 2023-02-13 +date: 2023-02-14 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 d2da431f68428..59f768ab27a66 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: 2023-02-13 +date: 2023-02-14 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 7c10ceda5424b..59b04799877f2 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,14 +8,14 @@ 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 161c5c13714d1..78deec6ad3d7e 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,14 +8,14 @@ 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index b31db09714554..e0a214619cca7 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,14 +8,14 @@ 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index 1c795f112bab9..6e359420604fe 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,14 +8,14 @@ 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index ac8d45fdceffe..d714edd40c04f 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,14 +8,14 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 6e046c1344dba..ec18cca3d342f 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,14 +8,14 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 74ead129e1195..aef7a99b5b5fe 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,14 +8,14 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; -Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) for questions regarding this plugin. +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. **Code health stats** diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index f9babf1a55f6b..12229de5c5b68 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: 2023-02-13 +date: 2023-02-14 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 b2b85f7e37c4b..b5ffcda85eff4 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: 2023-02-13 +date: 2023-02-14 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 2521b52ce0234..b516f98a3ee70 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: 2023-02-13 +date: 2023-02-14 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 22ee9b40be60b..ee7af575381a5 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: 2023-02-13 +date: 2023-02-14 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 aa77c11009b29..748a50530d642 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index 934dffcadb993..ef73b1eefd28c 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 728c88086d492..861511bf21b62 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: 2023-02-13 +date: 2023-02-14 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 543f5ef5b784b..c095f9b9d0b6f 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: 2023-02-13 +date: 2023-02-14 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 39b4f92825652..6d7e105718ae5 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: 2023-02-13 +date: 2023-02-14 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 9510ef82c0c45..629c48981ab2b 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: 2023-02-13 +date: 2023-02-14 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 7afa474345101..c47bc39db2e96 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: 2023-02-13 +date: 2023-02-14 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 e472fd409f0b5..dad3299bea34d 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: 2023-02-13 +date: 2023-02-14 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 e9e0730b6be1a..22c829625d325 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: 2023-02-13 +date: 2023-02-14 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 35c1c22510ec6..a9ee7172dac23 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs.mdx b/api_docs/kbn_ecs.mdx index 041a6dcdb99c6..b379d4decb8f6 100644 --- a/api_docs/kbn_ecs.mdx +++ b/api_docs/kbn_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs title: "@kbn/ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 0e2c2acfe927b..dd11448b38519 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 64f78fe84dfa8..f1294b97cb0e8 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 631ce9e67ddef..81107462cfd33 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: 2023-02-13 +date: 2023-02-14 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 673dd37f2986f..c4b7c17d2b7c0 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: 2023-02-13 +date: 2023-02-14 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 f5c2b2af98557..dc42fff33c905 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 77f31266d9baa..403f9369ebc35 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 6a0fa8bfe3ddf..ed047a12a0c79 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: 2023-02-13 +date: 2023-02-14 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 f5acaf43819ae..349e02470c107 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: 2023-02-13 +date: 2023-02-14 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 2ee7b663a20c0..478f9d79d4ec3 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: 2023-02-13 +date: 2023-02-14 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_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index 604213f9ab2f5..85c12fd927b8a 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 049ba94a844b7..47623d1f422bc 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index cd8b4ca92de8b..40a1fd85c74f5 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 405495dbada19..8a40c58858929 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: 2023-02-13 +date: 2023-02-14 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 bffa6c92c7acf..a7c8b3f81467c 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index 31bbcdae249f0..fffc9bdb47fd3 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index 0b30a75c841ad..be79ee0c7e616 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: 2023-02-13 +date: 2023-02-14 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 9e33307751194..ebc95d1b7ad09 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: 2023-02-13 +date: 2023-02-14 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 a19d44cd81070..de7e1cb6e0042 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index dd8ca1c9fbdb0..eee70dc6bc3c1 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index e2f3eb6b2d8a4..8f27466ec8cff 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: 2023-02-13 +date: 2023-02-14 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 9963f1ffc19fb..daaddd6cf1328 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: 2023-02-13 +date: 2023-02-14 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 51df3e0d42372..86d3ad6392b11 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: 2023-02-13 +date: 2023-02-14 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 92893a4cd7cc1..54a9684bcb1af 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index 5de3a5f9fe63a..46c3be46aa0a9 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 6adb002bba48b..08e47bb798ce7 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index 3f34de19742c8..7ca8d65b881e5 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index 53c7207c0fbe7..2a1cd7e5b1c7d 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index a820e75920c0e..1391630ce1138 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: 2023-02-13 +date: 2023-02-14 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 7ba7b0b6a1e0c..d11938ea6d69f 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: 2023-02-13 +date: 2023-02-14 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 ac07a7ea2f920..cad3a07756497 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: 2023-02-13 +date: 2023-02-14 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 62598444ca7ce..08f4db782c010 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: 2023-02-13 +date: 2023-02-14 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 bc5d037ce4284..54713eb9b8ebe 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: 2023-02-13 +date: 2023-02-14 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_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 5a3405751c0df..c4badade7ef76 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index b571e6d907980..6953805317c02 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index 98d507d216872..a064ea4ccc2f7 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: 2023-02-13 +date: 2023-02-14 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_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 58c0460ce917b..87f5c2d4f2129 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index c792afe50823a..1976b1b6a9452 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 21d695fdcd47e..e152611f7caca 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index c6f339a01a1e9..4b56aa9ef0138 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index b157058d2446d..2395d6468471a 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 621f886c51be5..cab8b13b8d6ec 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: 2023-02-13 +date: 2023-02-14 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 9386be13e253a..4cc52a283cf8a 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: 2023-02-13 +date: 2023-02-14 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 bc05ebfa6a281..98a6038eac610 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index 4c11bde76d985..ea059235ab9da 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index bf615de64694d..39c2e88f95296 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: 2023-02-13 +date: 2023-02-14 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 b53754946ed0f..4b889eaec00d2 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: 2023-02-13 +date: 2023-02-14 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 084789658465b..64353f110f72c 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: 2023-02-13 +date: 2023-02-14 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 b6ddd0c5b13f2..a85964afeb513 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 4569cc6b94e0e..1c2bf269d3244 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 2dd5b0a4ee296..635e9b64f4d86 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index f6bf1f58fa374..808aedcc49f8c 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 08531727639c9..967e5b79fedcf 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 453e61b915936..50349f5277331 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index d08acd1edcc7c..04c488619a394 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: 2023-02-13 +date: 2023-02-14 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 d43c78f7d9108..bccb147c42ec9 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index 3058573357bea..225bb7b17553d 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index c40592651df79..6401351cd21a3 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: 2023-02-13 +date: 2023-02-14 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_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index b20a686fcd813..856854a3cb5e5 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 5970e9d1083dc..677b759f2f427 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: 2023-02-13 +date: 2023-02-14 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 cb70e7eede04a..31d35bc632f41 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: 2023-02-13 +date: 2023-02-14 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 1230c51fb2441..3b3407e9ced98 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: 2023-02-13 +date: 2023-02-14 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 e82973502bc9b..9e76b742e44b1 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: 2023-02-13 +date: 2023-02-14 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 f8f39682e1faf..91c5c316a101a 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: 2023-02-13 +date: 2023-02-14 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 16442d24b6ab3..4136ca7336dab 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: 2023-02-13 +date: 2023-02-14 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 3a17ab676906d..f8630c337ba74 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: 2023-02-13 +date: 2023-02-14 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 87632efe414c5..2b05296b162cb 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: 2023-02-13 +date: 2023-02-14 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 0df26aabedc21..f63e62e9ab781 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: 2023-02-13 +date: 2023-02-14 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 b06a5a5c0b4ac..e0560fd206634 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: 2023-02-13 +date: 2023-02-14 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 283414599762d..07d42fd124cd0 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: 2023-02-13 +date: 2023-02-14 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 e7254db2141ae..b319ba66e82fe 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: 2023-02-13 +date: 2023-02-14 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 bd44e4257cb58..a2fb111cc1708 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: 2023-02-13 +date: 2023-02-14 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 2c0099ae8bbed..87b0e1ebb1ff3 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: 2023-02-13 +date: 2023-02-14 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 7702e974410a2..a815c5637a218 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index dd00049143c28..bd31a9b0650b2 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx index 5c7292571880e..e39417b400666 100644 --- a/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx +++ b/api_docs/kbn_shared_ux_avatar_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-user-profile-components title: "@kbn/shared-ux-avatar-user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-user-profile-components plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-user-profile-components'] --- import kbnSharedUxAvatarUserProfileComponentsObj from './kbn_shared_ux_avatar_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 2ecc8262beab8..3782c6ed8cfdb 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.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 713dd67bc8642..3f6710b1df1ee 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: 2023-02-13 +date: 2023-02-14 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 800c621fbb43c..b2552676b4802 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: 2023-02-13 +date: 2023-02-14 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 96c34d593da01..95a22758dd38f 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: 2023-02-13 +date: 2023-02-14 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 948bfb169e965..302d1f4b6ae2f 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: 2023-02-13 +date: 2023-02-14 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_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 546e1c0906e0c..c89052f4f2a83 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index ed7e027fd51f3..b9e69de0694b2 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index 9ba0ed2ad0950..e6697c1d05590 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 689c4ccc4e823..438125daf752e 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 77e32631b9bec..28dbdf8a3abfd 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 20838f81909a4..886894a1beb68 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 3feb6f3bbbe4e..70ab47d681c61 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index c4f8842d34235..80f6e66dd82db 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.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 2502679faa79f..84bf43097bf8a 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: 2023-02-13 +date: 2023-02-14 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_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 6112b556e4a67..65a620b5af198 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index 2fb00d3271803..bb3c77bb9c29a 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_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 5ae4843fe3981..90678e7733ce4 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: 2023-02-13 +date: 2023-02-14 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 1b4bc814a5531..81db9d0a7bd07 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: 2023-02-13 +date: 2023-02-14 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 52cd48fdc6dd5..7b11ee1c7ac38 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: 2023-02-13 +date: 2023-02-14 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 c4cc54de7d923..f09db83aaa817 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: 2023-02-13 +date: 2023-02-14 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 3275c06c40df3..f059aba456233 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: 2023-02-13 +date: 2023-02-14 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 90d4e2a7adf06..6f9ed41bbf8af 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: 2023-02-13 +date: 2023-02-14 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 14929e8dd6d94..dba236647c2d9 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: 2023-02-13 +date: 2023-02-14 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 37a46abdcebce..88a93ae2edde4 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: 2023-02-13 +date: 2023-02-14 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 1f336e80066be..852f7a1cc3059 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: 2023-02-13 +date: 2023-02-14 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 9f41a763a7f91..2572e5c26a269 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: 2023-02-13 +date: 2023-02-14 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 e79fb4d3c816b..151b375e2da8b 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: 2023-02-13 +date: 2023-02-14 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 6f2db9ad9c5f8..9c0e1ef6036ed 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: 2023-02-13 +date: 2023-02-14 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 7c6679869eff1..0c0f800a4b782 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: 2023-02-13 +date: 2023-02-14 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_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 3e82007577f93..a0e9f3e1703df 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 0d79c34e1a046..0447a4057ebee 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: 2023-02-13 +date: 2023-02-14 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 c8a053c8e61f0..fffee1f5ad5b1 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: 2023-02-13 +date: 2023-02-14 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 cf199168f5b2f..faf77c58a21ea 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: 2023-02-13 +date: 2023-02-14 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 988ef3033ca73..21516c199146b 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: 2023-02-13 +date: 2023-02-14 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 af50394e9ae21..255a79ba28f69 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.devdocs.json b/api_docs/kbn_slo_schema.devdocs.json index 74ba519202778..b62b90bafb2a2 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -490,7 +490,7 @@ "label": "FetchHistoricalSummaryResponse", "description": [], "signature": [ - "{ [x: string]: ({ date: string; } & { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; })[]; }" + "{ [x: string]: ({ date: string; } & { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; })[]; }" ], "path": "packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -520,7 +520,7 @@ "label": "FindSLOResponse", "description": [], "signature": [ - "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }" + "{ page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }" ], "path": "packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -535,7 +535,7 @@ "label": "GetSLOResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" ], "path": "packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -550,7 +550,7 @@ "label": "HistoricalSummaryResponse", "description": [], "signature": [ - "{ date: string; } & { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }" + "{ date: string; } & { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }" ], "path": "packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, @@ -595,7 +595,7 @@ "label": "SLOWithSummaryResponse", "description": [], "signature": [ - "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" + "{ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }" ], "path": "packages/kbn-slo-schema/src/rest_specs/slo.ts", "deprecated": false, diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 67659171defbd..f83de058f4a6d 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 520cb4004d740..8a7a76df2fceb 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 7b7cd37e84bdc..d63837cde4f99 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: 2023-02-13 +date: 2023-02-14 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 bf7ad4ef7e82a..eea60c75933ca 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: 2023-02-13 +date: 2023-02-14 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 7997fc4557d76..147ae3b18f860 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: 2023-02-13 +date: 2023-02-14 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 a83de1ea918d3..84335ee2505e8 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: 2023-02-13 +date: 2023-02-14 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 283e00a9e1b24..e2374eb1db418 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: 2023-02-13 +date: 2023-02-14 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 290b9c56dc787..c6429cd9dbae2 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index f8b259b11f915..ff6c20037f93d 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 2481fa9f3b945..c23a00f363164 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index a46aa622abe9a..ad0b92893283e 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index ddfd23a3a5502..f3ab381a0f8a1 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: 2023-02-13 +date: 2023-02-14 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_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index 6a09f3fae55f2..2ff2249164774 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 689b8bc2234a7..948e90d93ce2d 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index f510d34903490..13e93c4352a5e 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: 2023-02-13 +date: 2023-02-14 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 77fdb9ab2e142..d031ae591502e 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: 2023-02-13 +date: 2023-02-14 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 44ba603c98c1f..553bb149b6914 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: 2023-02-13 +date: 2023-02-14 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 3c9ca5f688bc9..0eb22e62f8b00 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: 2023-02-13 +date: 2023-02-14 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 b9263f3934050..eb2abe69e74c3 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: 2023-02-13 +date: 2023-02-14 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 bb542805a69f3..570b2ecc61765 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: 2023-02-13 +date: 2023-02-14 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 2849788e17b07..b0eef1f539e84 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: 2023-02-13 +date: 2023-02-14 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 53890e0c5aed0..d15b7b866bdf4 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: 2023-02-13 +date: 2023-02-14 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 01bbf1cc3692e..f77c7bb04a7df 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: 2023-02-13 +date: 2023-02-14 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 b707a04864ede..2da3cdc18b17f 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: 2023-02-13 +date: 2023-02-14 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 9fa245e331cb7..e167833037468 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: 2023-02-13 +date: 2023-02-14 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 0ea740f1706f4..fa69e6abc4306 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: 2023-02-13 +date: 2023-02-14 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 e8975328bdd65..cfacf1b52d5b5 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: 2023-02-13 +date: 2023-02-14 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 9826f4f96dacb..f49e0088eec21 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: 2023-02-13 +date: 2023-02-14 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 39e39d6333814..6146bd6915633 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: 2023-02-13 +date: 2023-02-14 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 b2824cb174e10..82e79240b9b69 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: 2023-02-13 +date: 2023-02-14 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 644623dca9238..56e65108d60e1 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: 2023-02-13 +date: 2023-02-14 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 8ed6069ab0761..35b02eb19fa5c 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/ml.devdocs.json b/api_docs/ml.devdocs.json index d58430fd0174c..e74cc17d3cb82 100644 --- a/api_docs/ml.devdocs.json +++ b/api_docs/ml.devdocs.json @@ -310,7 +310,7 @@ "MlLocator", " | undefined; } | undefined, basePath: string | undefined, params: ", "MlLocatorParams", - ") => string" + ", dependencies?: React.DependencyList | undefined) => string" ], "path": "x-pack/plugins/ml/public/locator/use_ml_href.ts", "deprecated": false, @@ -362,6 +362,21 @@ "deprecated": false, "trackAdoption": false, "isRequired": true + }, + { + "parentPluginId": "ml", + "id": "def-public.useMlHref.$4", + "type": "Object", + "tags": [], + "label": "dependencies", + "description": [], + "signature": [ + "React.DependencyList | undefined" + ], + "path": "x-pack/plugins/ml/public/locator/use_ml_href.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false } ], "returnComment": [], diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index c62094946f441..09cc61ce91624 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) for questi | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 255 | 9 | 79 | 40 | +| 256 | 9 | 80 | 40 | ## Client diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 9ad61bd757a64..be02aacb1b070 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: 2023-02-13 +date: 2023-02-14 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 ef64b46221a91..ed410652814b9 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: 2023-02-13 +date: 2023-02-14 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 26e2a38fa6e0b..b11c1d9fe6510 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: 2023-02-13 +date: 2023-02-14 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 c219815c61506..55861842ce908 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 9c175656ce6e5..2c550dbf081f7 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 26947d3989b12..81657e3824308 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -10037,7 +10037,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }, ", + ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }, ", { "pluginId": "observability", "scope": "server", @@ -10085,7 +10085,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }, ", + ", { page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }, ", { "pluginId": "observability", "scope": "server", @@ -10117,7 +10117,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { [x: string]: ({ date: string; } & { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; })[]; }, ", + ", { [x: string]: ({ date: string; } & { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; })[]; }, ", { "pluginId": "observability", "scope": "server", @@ -10751,7 +10751,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }, ", + ", { id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; }, ", { "pluginId": "observability", "scope": "server", @@ -10799,7 +10799,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }, ", + ", { page: number; perPage: number; total: number; results: ({ id: string; name: string; description: string; indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; 'threshold.us': number; } & { index?: string | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; } & { goodStatusCodes?: (\"2xx\" | \"3xx\" | \"4xx\" | \"5xx\")[] | undefined; index?: string | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; filter: string; good: string; total: string; }; }; timeWindow: { duration: string; isRolling: boolean; } | { duration: string; calendar: { startTime: string; }; }; budgetingMethod: \"occurrences\" | \"timeslices\"; objective: { target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: string | undefined; }; revision: number; settings: { timestampField: string; syncDelay: string; frequency: string; }; enabled: boolean; createdAt: string; updatedAt: string; } & { summary: { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; }; })[]; }, ", { "pluginId": "observability", "scope": "server", @@ -10831,7 +10831,7 @@ "section": "def-server.ObservabilityRouteHandlerResources", "text": "ObservabilityRouteHandlerResources" }, - ", { [x: string]: ({ date: string; } & { status: \"NO_DATA\" | \"HEALTHY\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; })[]; }, ", + ", { [x: string]: ({ date: string; } & { status: \"HEALTHY\" | \"NO_DATA\" | \"DEGRADING\" | \"VIOLATED\"; sliValue: number; errorBudget: { initial: number; consumed: number; remaining: number; isEstimated: boolean; }; })[]; }, ", { "pluginId": "observability", "scope": "server", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 3fa43ac682ae4..fcc9c5e5efdc4 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: 2023-02-13 +date: 2023-02-14 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 582736a831e2e..2c546f80e1758 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: 2023-02-13 +date: 2023-02-14 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 a608234e314ff..535ff70d31e9f 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,16 +21,16 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 67468 | 512 | 58461 | 1225 | +| 67459 | 512 | 58452 | 1222 | ## Plugin Directory | Plugin name           | Maintaining team | Description | API Cnt | Any Cnt | Missing
comments | Missing
exports | |--------------|----------------|-----------|--------------|----------|---------------|--------| | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 256 | 8 | 251 | 24 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 36 | 1 | 32 | 2 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 36 | 1 | 32 | 2 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 12 | 0 | 1 | 2 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 476 | 1 | 466 | 39 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 488 | 1 | 477 | 39 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 42 | 0 | 42 | 65 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 89 | 1 | 74 | 2 | @@ -47,7 +47,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | cloudLinks | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | Adds the links to the Elastic Cloud console | 0 | 0 | 0 | 0 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | The cloud security posture plugin | 17 | 0 | 2 | 2 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 13 | 0 | 13 | 1 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Content management app | 22 | 0 | 22 | 1 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Content management app | 25 | 0 | 25 | 3 | | | [@elastic/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 | 270 | 0 | 266 | 9 | | crossClusterReplication | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 0 | 0 | 0 | 0 | | customBranding | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Enables customization of Kibana | 0 | 0 | 0 | 0 | @@ -90,7 +90,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | 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 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 254 | 1 | 45 | 5 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Simple UI for managing files in Kibana | 2 | 1 | 2 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1069 | 3 | 964 | 26 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1077 | 3 | 972 | 26 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | @@ -121,7 +121,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 41 | 0 | 41 | 6 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 267 | 0 | 266 | 27 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 67 | 0 | 67 | 0 | -| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 255 | 9 | 79 | 40 | +| | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 256 | 9 | 80 | 40 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 15 | 3 | 13 | 1 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 9 | 0 | 9 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 34 | 0 | 34 | 2 | @@ -164,7 +164,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 257 | 1 | 214 | 20 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [@elastic/kibana-localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 591 | 11 | 562 | 53 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 558 | 11 | 529 | 48 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Adds UI Actions service to Kibana | 134 | 2 | 92 | 9 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Extends UI Actions plugin with more functionality | 206 | 0 | 140 | 9 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Contains functionality for the field list which can be integrated into apps | 267 | 0 | 242 | 7 | @@ -213,7 +213,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | - | 11 | 0 | 11 | 0 | | | [@elastic/kibana-qa](https://github.com/orgs/elastic/teams/kibana-qa) | - | 10 | 0 | 10 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 19 | 0 | 17 | 0 | -| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 20 | 0 | 14 | 3 | +| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 20 | 0 | 15 | 3 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 4 | 0 | 4 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 76 | 0 | 76 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 7 | 0 | 2 | 0 | @@ -373,13 +373,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 4 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2 | 0 | 1 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 6 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 30 | 1 | 18 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 11 | 1 | 11 | 3 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 8 | 0 | 8 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 24 | 0 | 3 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 32 | 1 | 16 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 18 | 1 | 17 | 3 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 6 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 30 | 1 | 18 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 11 | 1 | 11 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 8 | 0 | 8 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 24 | 0 | 3 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 1 | 16 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 18 | 1 | 17 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 6 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 153 | 0 | 142 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 8 | 0 | 8 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 7 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 72e33ef7a002e..9dbd57f02eb95 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index ecdb36a0c35b3..4d85f1b1c042f 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index ab0f16134c3d6..f1254b279ec36 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: 2023-02-13 +date: 2023-02-14 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 3d2cfdd706a07..d7e0be1c9d74e 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: 2023-02-13 +date: 2023-02-14 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 d39a12e96c625..1280efe273009 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: 2023-02-13 +date: 2023-02-14 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 5e561b0adb09b..b098acea5fb03 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -1538,7 +1538,7 @@ "section": "def-server.GetSummarizedAlertsFnOpts", "text": "GetSummarizedAlertsFnOpts" }, - ") => Promise<{ new: { count: number; data: {}[]; }; ongoing: { count: number; data: {}[]; }; recovered: { count: number; data: {}[]; }; }>" + ") => Promise<{ new: { count: number; data: { _id: string; _index: string; }[]; }; ongoing: { count: number; data: { _id: string; _index: string; }[]; }; recovered: { count: number; data: { _id: string; _index: string; }[]; }; }>" ], "path": "x-pack/plugins/rule_registry/server/utils/create_get_summarized_alerts_fn.ts", "deprecated": false, @@ -1883,7 +1883,7 @@ "section": "def-server.GetSummarizedAlertsFnOpts", "text": "GetSummarizedAlertsFnOpts" }, - ") => Promise<{ new: { count: number; data: {}[]; }; ongoing: { count: number; data: {}[]; }; recovered: { count: number; data: {}[]; }; }>; id: string; name: string; validate?: { params?: ", + ") => Promise<{ new: { count: number; data: { _id: string; _index: string; }[]; }; ongoing: { count: number; data: { _id: string; _index: string; }[]; }; recovered: { count: number; data: { _id: string; _index: string; }[]; }; }>; id: string; name: string; validate?: { params?: ", "RuleTypeParamsValidator", " | undefined; } | undefined; cancelAlertsOnRuleTimeout?: boolean | undefined; alerts?: ", "IRuleTypeAlerts", diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 05243f30e862a..a72576e955b89 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: 2023-02-13 +date: 2023-02-14 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 e5962fe15acbf..ee6399da104b7 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: 2023-02-13 +date: 2023-02-14 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 83399d5aee837..8c1f3c10a410e 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: 2023-02-13 +date: 2023-02-14 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 75c20dcee612e..ccbe4ed63f976 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: 2023-02-13 +date: 2023-02-14 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 eb11161bd3201..a2ef1edd172e0 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: 2023-02-13 +date: 2023-02-14 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 2892131464fdb..fb2041e385442 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: 2023-02-13 +date: 2023-02-14 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 ed859529d609d..f0c3ef27790c7 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: 2023-02-13 +date: 2023-02-14 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 aa2ad1bb158f3..373342f3bc7a1 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: 2023-02-13 +date: 2023-02-14 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 d1fb5659c6922..0fac03f8c31b3 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: 2023-02-13 +date: 2023-02-14 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 edcc16163bfd3..76ad6920d27a2 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: 2023-02-13 +date: 2023-02-14 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 2673c43acfe2d..51635a0b73053 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: 2023-02-13 +date: 2023-02-14 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 abc795f10a11c..a8a5826af9f34 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: 2023-02-13 +date: 2023-02-14 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 ee264c0490fdf..cb43a2e943249 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: 2023-02-13 +date: 2023-02-14 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 54172422e2882..1661a83ab6d05 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: 2023-02-13 +date: 2023-02-14 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 0d2c8b22fe326..d64484c8d75c8 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: 2023-02-13 +date: 2023-02-14 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 78a66e91d60a1..29e555cd52aa7 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: 2023-02-13 +date: 2023-02-14 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 f3f8bac8ef053..f4a814e8cf855 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index cd780ce57cfa2..ffd74545048f5 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index ab837d198ef7d..1f71856f5e7d6 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: 2023-02-13 +date: 2023-02-14 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 71454f14e5988..46ecb3587913e 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: 2023-02-13 +date: 2023-02-14 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 4b1e480727ec9..b4024288f6015 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: 2023-02-13 +date: 2023-02-14 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 6976781c35cba..4a8a10c0fa569 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: 2023-02-13 +date: 2023-02-14 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 7bff3462cb8aa..5db82a98dddca 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: 2023-02-13 +date: 2023-02-14 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 cb3915bb23bfa..1f88c72a8493c 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: 2023-02-13 +date: 2023-02-14 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 9d55be5678b85..ed16da672748d 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: 2023-02-13 +date: 2023-02-14 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 ce28d89951f5e..3a9f03aa9ebc3 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.devdocs.json b/api_docs/triggers_actions_ui.devdocs.json index 4d406dbab5260..8bc730bca1680 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -931,66 +931,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadActionErrorLog", - "type": "Function", - "tags": [], - "label": "loadActionErrorLog", - "description": [], - "signature": [ - "({ id, http, dateStart, dateEnd, runId, message, perPage, page, sort, namespace, withAuth, }: ", - "LoadActionErrorLogProps", - " & { http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise<", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.IExecutionErrorsResult", - "text": "IExecutionErrorsResult" - }, - ">" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_action_error_log.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadActionErrorLog.$1", - "type": "CompoundType", - "tags": [], - "label": "{\n id,\n http,\n dateStart,\n dateEnd,\n runId,\n message,\n perPage = 10,\n page = 0,\n sort,\n namespace,\n withAuth = false,\n}", - "description": [], - "signature": [ - "LoadActionErrorLogProps", - " & { http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_action_error_log.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "triggersActionsUi", "id": "def-public.loadActionTypes", @@ -1072,133 +1012,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadAllActions", - "type": "Function", - "tags": [], - "label": "loadAllActions", - "description": [], - "signature": [ - "({ http }: { http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise<", - { - "pluginId": "triggersActionsUi", - "scope": "public", - "docId": "kibTriggersActionsUiPluginApi", - "section": "def-public.ActionConnector", - "text": "ActionConnector" - }, - ", Record>[]>" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connectors.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadAllActions.$1", - "type": "Object", - "tags": [], - "label": "{ http }", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connectors.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadAllActions.$1.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/action_connector_api/connectors.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadExecutionLogAggregations", - "type": "Function", - "tags": [], - "label": "loadExecutionLogAggregations", - "description": [], - "signature": [ - "({ id, http, dateStart, dateEnd, outcomeFilter, message, perPage, page, sort, }: ", - "LoadExecutionLogAggregationsProps", - " & { http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise<", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.IExecutionLogResult", - "text": "IExecutionLogResult" - }, - ">" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadExecutionLogAggregations.$1", - "type": "CompoundType", - "tags": [], - "label": "{\n id,\n http,\n dateStart,\n dateEnd,\n outcomeFilter,\n message,\n perPage = 10,\n page = 0,\n sort = [],\n}", - "description": [], - "signature": [ - "LoadExecutionLogAggregationsProps", - " & { http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/load_execution_log_aggregations.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "triggersActionsUi", "id": "def-public.loadRule", @@ -1322,57 +1135,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRules", - "type": "Function", - "tags": [], - "label": "loadRules", - "description": [], - "signature": [ - "({\n http,\n page,\n searchText,\n typesFilter,\n actionTypesFilter,\n ruleExecutionStatusesFilter,\n ruleStatusesFilter,\n tagsFilter,\n sort = { field: 'name', direction: 'asc' },\n}: ", - "LoadRulesProps", - ") => Promise<{ page: number; perPage: number; total: number; data: ", - { - "pluginId": "triggersActionsUi", - "scope": "public", - "docId": "kibTriggersActionsUiPluginApi", - "section": "def-public.Rule", - "text": "Rule" - }, - "<", - { - "pluginId": "alerting", - "scope": "common", - "docId": "kibAlertingPluginApi", - "section": "def-common.RuleTypeParams", - "text": "RuleTypeParams" - }, - ">[]; }>" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRules.$1", - "type": "Object", - "tags": [], - "label": "{\n http,\n page,\n searchText,\n typesFilter,\n actionTypesFilter,\n ruleExecutionStatusesFilter,\n ruleStatusesFilter,\n tagsFilter,\n sort = { field: 'name', direction: 'asc' },\n}", - "description": [], - "signature": [ - "LoadRulesProps" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "triggersActionsUi", "id": "def-public.loadRuleSummary", @@ -1451,139 +1213,11 @@ "type": "number", "tags": [], "label": "numberOfExecutions", - "description": [], - "signature": [ - "number | undefined" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rule_summary.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRuleTags", - "type": "Function", - "tags": [], - "label": "loadRuleTags", - "description": [], - "signature": [ - "({ http }: { http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise<", - "RuleTagsAggregations", - ">" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRuleTags.$1", - "type": "Object", - "tags": [], - "label": "{ http }", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRuleTags.$1.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRuleTypes", - "type": "Function", - "tags": [], - "label": "loadRuleTypes", - "description": [], - "signature": [ - "({ http }: { http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise<", - { - "pluginId": "triggersActionsUi", - "scope": "public", - "docId": "kibTriggersActionsUiPluginApi", - "section": "def-public.RuleType", - "text": "RuleType" - }, - "[]>" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rule_types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRuleTypes.$1", - "type": "Object", - "tags": [], - "label": "{ http }", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rule_types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.loadRuleTypes.$1.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } + "description": [], + "signature": [ + "number | undefined" ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rule_types.ts", + "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rule_summary.ts", "deprecated": false, "trackAdoption": false } @@ -1626,76 +1260,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.muteRule", - "type": "Function", - "tags": [], - "label": "muteRule", - "description": [], - "signature": [ - "({ id, http }: { id: string; http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/mute.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.muteRule.$1", - "type": "Object", - "tags": [], - "label": "{ id, http }", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/mute.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.muteRule.$1.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/mute.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.muteRule.$1.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/mute.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "triggersActionsUi", "id": "def-public.OfExpression", @@ -1827,92 +1391,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.snoozeRule", - "type": "Function", - "tags": [], - "label": "snoozeRule", - "description": [], - "signature": [ - "({\n id,\n snoozeSchedule,\n http,\n}: { id: string; snoozeSchedule: ", - "SnoozeSchedule", - "; http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/snooze.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.snoozeRule.$1", - "type": "Object", - "tags": [], - "label": "{\n id,\n snoozeSchedule,\n http,\n}", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/snooze.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.snoozeRule.$1.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/snooze.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.snoozeRule.$1.snoozeSchedule", - "type": "Object", - "tags": [], - "label": "snoozeSchedule", - "description": [], - "signature": [ - "SnoozeSchedule" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/snooze.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.snoozeRule.$1.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/snooze.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "triggersActionsUi", "id": "def-public.suspendedComponentWithProps", @@ -2108,160 +1586,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unmuteRule", - "type": "Function", - "tags": [], - "label": "unmuteRule", - "description": [], - "signature": [ - "({ id, http }: { id: string; http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; }) => Promise" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unmute.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unmuteRule.$1", - "type": "Object", - "tags": [], - "label": "{ id, http }", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unmute.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unmuteRule.$1.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unmute.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unmuteRule.$1.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unmute.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unsnoozeRule", - "type": "Function", - "tags": [], - "label": "unsnoozeRule", - "description": [], - "signature": [ - "({\n id,\n http,\n scheduleIds,\n}: { id: string; http: ", - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - }, - "; scheduleIds?: string[] | undefined; }) => Promise" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unsnooze.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unsnoozeRule.$1", - "type": "Object", - "tags": [], - "label": "{\n id,\n http,\n scheduleIds,\n}", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unsnooze.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unsnoozeRule.$1.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unsnooze.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unsnoozeRule.$1.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-http-browser", - "scope": "common", - "docId": "kibKbnCoreHttpBrowserPluginApi", - "section": "def-common.HttpSetup", - "text": "HttpSetup" - } - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unsnooze.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "triggersActionsUi", - "id": "def-public.unsnoozeRule.$1.scheduleIds", - "type": "Array", - "tags": [], - "label": "scheduleIds", - "description": [], - "signature": [ - "string[] | undefined" - ], - "path": "x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/unsnooze.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "triggersActionsUi", "id": "def-public.updateActionConnector", diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 3502cbbd5077d..e675491c490a1 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 591 | 11 | 562 | 53 | +| 558 | 11 | 529 | 48 | ## Client diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index ae7f45fb857ae..833664ef118cd 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: 2023-02-13 +date: 2023-02-14 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 3a230359dc24f..8927a9d901ac2 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: 2023-02-13 +date: 2023-02-14 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 81459c6aa9808..ce44a303c9b83 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedFieldList'] --- import unifiedFieldListObj from './unified_field_list.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index cee3f30609fbd..707c9bc1caa40 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 1d749925972f6..9cd42b146dbef 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: 2023-02-13 +date: 2023-02-14 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 e4922e0fb12a8..31b03898ef3c0 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: 2023-02-13 +date: 2023-02-14 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 49615f3bec49e..0a2b86789f368 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: 2023-02-13 +date: 2023-02-14 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 2bab1a92ced30..7a7f960493d5d 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: 2023-02-13 +date: 2023-02-14 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 0168070756467..16da9aa953ab3 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: 2023-02-13 +date: 2023-02-14 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 7751260fc8a24..fca55ee689d2b 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: 2023-02-13 +date: 2023-02-14 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 f47c85e4e8bd1..1785433cf74a9 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: 2023-02-13 +date: 2023-02-14 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 50cabc3f8ac12..c6c8f6276ec30 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: 2023-02-13 +date: 2023-02-14 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 27abcbd227516..cfade46a245b1 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: 2023-02-13 +date: 2023-02-14 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 dcb1c7358a000..2eb774981b798 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: 2023-02-13 +date: 2023-02-14 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 67a8624c68790..ee914d59bc5eb 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: 2023-02-13 +date: 2023-02-14 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 f2a574b6f03d7..7cfe89820e844 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: 2023-02-13 +date: 2023-02-14 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 8768104eadb23..f133b2e6251c4 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: 2023-02-13 +date: 2023-02-14 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 b9844cb52d9b1..87255c4d0e687 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: 2023-02-13 +date: 2023-02-14 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 49b5463fd7950..2eba4ed8d7789 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: 2023-02-13 +date: 2023-02-14 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 8c4c8d4fd1c48..d9f770b38e06e 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: 2023-02-13 +date: 2023-02-14 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From da89dde7acb58d2818fa0a5327a9f03c456287c4 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 14 Feb 2023 08:44:11 +0100 Subject: [PATCH 155/203] [codeql] Do not run GitHub CodeQL Action on forks (#150974) It turned out that the CodeQL action also runs on forks which generate a lot of noise in the form of security e-mails to the owners of those forks. --- .github/workflows/codeql.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f221a780c7422..d7fd5af4266c9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,6 +12,7 @@ jobs: actions: read contents: read security-events: write + if: github.repository == 'elastic/kibana' # Hack: Do not run on forks strategy: fail-fast: false From ace5c10c2c3ef8a594a637e59ae7f11169ce9b0c Mon Sep 17 00:00:00 2001 From: Ievgen Sorokopud Date: Tue, 14 Feb 2023 09:41:29 +0100 Subject: [PATCH 156/203] [Security Solution] When adding an Exception and Source value on the Severity override option, are not offering suggestions (#150701) ## Summary These changes fixes the issue with the broken field source value auto-suggestion which was caused by [this PR](https://github.com/elastic/kibana/pull/149149/files#diff-2b9142306df119b8c31e8a66c9b93b2a83f74239b1655919881165ac06398623R148). The problem is that the `stringifyIndices` variable is used to: 1. represent all indices down the road where we request suggestions for a field in `src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts` 2. be a parameter to check whether we should memoize the results of `getIndexFields` and `getDataViewStateFromIndexFields` methods By modifying it to include the notion of whether we should include unmapped information, solves the second point but breaks the first one. Thus, suggestion request stopped working. The fix is to revert changes to `stringifyIndices` variable and add extra parameter to `getIndexFields` and `getDataViewStateFromIndexFields` methods, so that we can take into account `includeUnmapped` flag during memoization. Bug ticket #150663 --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../add_edit_flyout/flyout_validation.cy.ts | 19 +++++++++++++++++- .../public/common/containers/source/index.tsx | 20 ++++++++++++------- .../containers/source/use_data_view.tsx | 7 +++++-- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts index f96af6b5f2572..dda1115979e29 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/exceptions/add_edit_flyout/flyout_validation.cy.ts @@ -74,7 +74,7 @@ describe('Exceptions flyout', () => { createExceptionList(getExceptionList(), getExceptionList().list_id).then((response) => createCustomRule({ ...getNewRule(), - dataSource: { index: ['exceptions-*'], type: 'indexPatterns' }, + dataSource: { index: ['auditbeat-*', 'exceptions-*'], type: 'indexPatterns' }, exceptionLists: [ { id: response.body.id, @@ -289,11 +289,28 @@ describe('Exceptions flyout', () => { openExceptionFlyoutFromEmptyViewerPrompt(); cy.get(FIELD_INPUT).eq(0).click({ force: true }); + cy.get(FIELD_INPUT).eq(0).type('unique'); cy.get(EXCEPTION_FIELD_LIST).contains('unique_value.test'); closeExceptionBuilderFlyout(); }); + it('Validates auto-suggested fields correctly', () => { + // open add exception modal + openExceptionFlyoutFromEmptyViewerPrompt(); + + // add exception item name + addExceptionFlyoutItemName('My item name'); + + // add an entry with a value and submit button should enable + addExceptionEntryFieldValue('agent.type', 0); + cy.get(VALUES_INPUT).eq(0).type(`{enter}`); + cy.get(VALUES_INPUT).eq(0).type(`{downarrow}{enter}`); + cy.get(CONFIRM_BTN).should('be.enabled'); + + closeExceptionBuilderFlyout(); + }); + // TODO - Add back in error states into modal describe.skip('flyout errors', () => { beforeEach(() => { diff --git a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx index e154eb1f5edfe..09eb4f7a47230 100644 --- a/x-pack/plugins/security_solution/public/common/containers/source/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/source/index.tsx @@ -43,7 +43,7 @@ export const getAllFieldsByName = ( keyBy('name', getAllBrowserFields(browserFields)); export const getIndexFields = memoizeOne( - (title: string, fields: IndexField[]): DataViewBase => + (title: string, fields: IndexField[], _includeUnmapped: boolean = false): DataViewBase => fields && fields.length > 0 ? { fields: fields.map((field) => @@ -63,7 +63,10 @@ export const getIndexFields = memoizeOne( title, } : { fields: [], title }, - (newArgs, lastArgs) => newArgs[0] === lastArgs[0] && newArgs[1].length === lastArgs[1].length + (newArgs, lastArgs) => + newArgs[0] === lastArgs[0] && + newArgs[1].length === lastArgs[1].length && + newArgs[2] === lastArgs[2] ); /** @@ -145,21 +148,24 @@ export const useFetchIndex = ( if (isCompleteResponse(response)) { Promise.resolve().then(() => { ReactDOM.unstable_batchedUpdates(() => { - const stringifyIndices = `${response.indicesExist - .sort() - .join()} (includeUnmapped: ${includeUnmapped})`; + const stringifyIndices = response.indicesExist.sort().join(); previousIndexesName.current = response.indicesExist; const { browserFields } = getDataViewStateFromIndexFields( stringifyIndices, - response.indexFields + response.indexFields, + includeUnmapped ); setLoading(false); setState({ browserFields, indexes: response.indicesExist, indexExists: response.indicesExist.length > 0, - indexPatterns: getIndexFields(stringifyIndices, response.indexFields), + indexPatterns: getIndexFields( + stringifyIndices, + response.indexFields, + includeUnmapped + ), }); searchSubscription$.current.unsubscribe(); 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 ef8eac73ba136..32533d2d7c577 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 @@ -50,7 +50,7 @@ interface DataViewInfo { * VERY mutatious on purpose to improve the performance of the transform. */ export const getDataViewStateFromIndexFields = memoizeOne( - (_title: string, fields: IndexField[]): DataViewInfo => { + (_title: string, fields: IndexField[], _includeUnmapped: boolean = false): DataViewInfo => { // Adds two dangerous casts to allow for mutations within this function type DangerCastForMutation = Record; @@ -78,7 +78,10 @@ export const getDataViewStateFromIndexFields = memoizeOne( } ); }, - (newArgs, lastArgs) => newArgs[0] === lastArgs[0] && newArgs[1].length === lastArgs[1].length + (newArgs, lastArgs) => + newArgs[0] === lastArgs[0] && + newArgs[1].length === lastArgs[1].length && + newArgs[2] === lastArgs[2] ); export const useDataView = (): { From ea646dfe04799775de988dfb34248001e23e4437 Mon Sep 17 00:00:00 2001 From: Faisal Kanout Date: Tue, 14 Feb 2023 10:04:24 +0100 Subject: [PATCH 157/203] [BUG] [AO] - Fix alert evaluation value format in the alert flyout (#150720) ## Summary It closes #101945 It closes #150857 by using the formatter from the Observability plugin. ### Before ### ms Screenshot 2023-02-09 at 15 49 12 ### % Screenshot 2023-02-10 at 12 28 34 ### After ### ms Screenshot 2023-02-09 at 15 48 58 ### % Screenshot 2023-02-10 at 13 17 20 --- .../components/alerts_flyout/alerts_flyout_body.tsx | 12 ++++++++++-- .../apps/observability/pages/alerts/index.ts | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_body.tsx b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_body.tsx index ead2b83388f87..97343a11cd498 100644 --- a/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_body.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/components/alerts_flyout/alerts_flyout_body.tsx @@ -21,6 +21,7 @@ import { ALERT_EVALUATION_VALUE, ALERT_FLAPPING, ALERT_RULE_CATEGORY, + ALERT_RULE_TYPE_ID, ALERT_RULE_UUID, ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, @@ -32,6 +33,7 @@ import { RULE_DETAILS_PAGE_ID } from '../../../rule_details/constants'; import { asDuration } from '../../../../../common/utils/formatters'; import { translations, paths } from '../../../../config'; import { FlyoutProps } from './types'; +import { formatAlertEvaluationValue } from '../../../../utils/format_alert_evaluation_value'; // eslint-disable-next-line import/no-default-export export default function AlertsFlyoutBody({ alert, id: pageId }: FlyoutProps) { @@ -74,11 +76,17 @@ export default function AlertsFlyoutBody({ alert, id: pageId }: FlyoutProps) { }, { title: translations.alertsFlyout.expectedValueLabel, - description: alert.fields[ALERT_EVALUATION_THRESHOLD] ?? '-', + description: formatAlertEvaluationValue( + alert.fields[ALERT_RULE_TYPE_ID], + alert.fields[ALERT_EVALUATION_THRESHOLD] + ), }, { title: translations.alertsFlyout.actualValueLabel, - description: alert.fields[ALERT_EVALUATION_VALUE] ?? '-', + description: formatAlertEvaluationValue( + alert.fields[ALERT_RULE_TYPE_ID], + alert.fields[ALERT_EVALUATION_VALUE] + ), }, { title: translations.alertsFlyout.ruleTypeLabel, 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 8c386e99423ce..99c41f250ab07 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 @@ -170,8 +170,8 @@ export default ({ getService }: FtrProviderContext) => { 'Oct 19, 2021 @ 15:00:41.555', 'Oct 19, 2021 @ 15:20:38.749', '20 minutes', - '5', - '30.73', + '5.0%', + '31%', 'Failed transaction rate threshold', ]; From 868fc247a944f55c15ac5a0a3ced1887dd9ac72e Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Tue, 14 Feb 2023 10:27:35 +0100 Subject: [PATCH 158/203] [SharedUX] Add custom branding to ExitFullScreenButton (#150620) ## Summary This PR replaces the Elastic logo with the custom logo in `ExitFullScreenButton` component. Without custom logo: Screenshot 2023-02-13 at 12 49 59 With custom logo: Screenshot 2023-02-13 at 12 53 16 ### Checklist Delete any items that are not applicable to this PR. ~- [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~ ~- [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials~ - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [X] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [X] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) ~- [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) ~- [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers)~ ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../exit_full_screen_button.test.tsx.snap | 48 +++++++++++++++++++ .../src/exit_full_screen_button.component.tsx | 9 +++- .../impl/src/exit_full_screen_button.test.tsx | 11 +++++ .../impl/src/exit_full_screen_button.tsx | 7 ++- .../exit_full_screen/impl/src/services.tsx | 1 + .../button/exit_full_screen/mocks/src/jest.ts | 5 ++ .../exit_full_screen/mocks/src/storybook.ts | 2 + .../button/exit_full_screen/types/index.d.ts | 9 ++++ .../exit_full_screen/types/tsconfig.json | 3 ++ .../embeddable/dashboard_container.tsx | 6 ++- .../custom_branding/custom_branding.stub.ts | 1 + .../custom_branding_service.ts | 1 + .../public/services/custom_branding/types.ts | 1 + 13 files changed, 99 insertions(+), 5 deletions(-) diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/__snapshots__/exit_full_screen_button.test.tsx.snap b/packages/shared-ux/button/exit_full_screen/impl/src/__snapshots__/exit_full_screen_button.test.tsx.snap index c3dbe9dc42bfc..137956b648c2c 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/__snapshots__/exit_full_screen_button.test.tsx.snap +++ b/packages/shared-ux/button/exit_full_screen/impl/src/__snapshots__/exit_full_screen_button.test.tsx.snap @@ -41,6 +41,54 @@ exports[` with kibana services is rendered 1`] = `
`; +exports[` with kibana services renders custom logo 1`] = ` +
+

+ In full screen mode, press ESC to exit. +

+ +
+`; + exports[` with manual services is rendered 1`] = `

{ +export const ExitFullScreenButton = ({ onClick, className, customLogo }: Props) => { const { euiTheme } = useEuiTheme(); const { colors, size, border } = euiTheme; @@ -63,7 +64,11 @@ export const ExitFullScreenButton = ({ onClick, className }: Props) => { > - + {customLogo ? ( + + ) : ( + + )} {text} diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.test.tsx b/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.test.tsx index 1d2bf1d9aaa58..016762e470f97 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.test.tsx +++ b/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.test.tsx @@ -17,6 +17,7 @@ import { import { ExitFullScreenButton } from './exit_full_screen_button'; import { ExitFullScreenButtonKibanaProvider, ExitFullScreenButtonProvider } from './services'; +import { of } from 'rxjs'; const componentServices = getExitFullScreenButtonServicesMock(); const kibanaServices = getExitFullScreenButtonKibanaDependenciesMock(); @@ -103,6 +104,16 @@ describe('', () => { expect(kibanaServices.coreStart.chrome.setIsVisible).toHaveBeenCalledTimes(0); }); + test('renders custom logo', () => { + kibanaServices.coreStart.customBranding.customBranding$ = of({ + logo: 'imageSrcAsBase64encodedstring', + }); + const component = kibanaMount( + + ); + expect(component.render()).toMatchSnapshot(); + }); + describe('onExit', () => { const onExitHandler = jest.fn(); let component: ReactWrapper; diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.tsx b/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.tsx index ada7075514e9c..dc70d1de3e453 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.tsx +++ b/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.tsx @@ -13,6 +13,7 @@ import useMountedState from 'react-use/lib/useMountedState'; import type { ExitFullScreenButtonProps as Props } from '@kbn/shared-ux-button-exit-full-screen-types'; +import useObservable from 'react-use/lib/useObservable'; import { ExitFullScreenButton as Component } from './exit_full_screen_button.component'; import { useServices } from './services'; @@ -22,8 +23,10 @@ import { useServices } from './services'; */ export const ExitFullScreenButton = ({ onExit = () => {}, toggleChrome = true }: Props) => { const { euiTheme } = useEuiTheme(); - const { setIsFullscreen } = useServices(); + const { setIsFullscreen, customBranding$ } = useServices(); const isMounted = useMountedState(); + const customBranding = useObservable(customBranding$); + const customLogo = customBranding?.logo; const onClick = useCallback(() => { if (toggleChrome) { @@ -70,5 +73,5 @@ export const ExitFullScreenButton = ({ onExit = () => {}, toggleChrome = true }: z-index: 5; `; - return ; + return ; }; diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/services.tsx b/packages/shared-ux/button/exit_full_screen/impl/src/services.tsx index da6ce5cbcbc8c..909b63e77ed68 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/services.tsx +++ b/packages/shared-ux/button/exit_full_screen/impl/src/services.tsx @@ -43,6 +43,7 @@ export const ExitFullScreenButtonKibanaProvider: FC { services.coreStart.chrome.setIsVisible(!isFullscreen); }, + customBranding$: services.coreStart.customBranding.customBranding$, }} > {children} diff --git a/packages/shared-ux/button/exit_full_screen/mocks/src/jest.ts b/packages/shared-ux/button/exit_full_screen/mocks/src/jest.ts index f763c28c9015e..917595d441d6e 100644 --- a/packages/shared-ux/button/exit_full_screen/mocks/src/jest.ts +++ b/packages/shared-ux/button/exit_full_screen/mocks/src/jest.ts @@ -10,6 +10,7 @@ import { ExitFullScreenButtonKibanaDependencies, ExitFullScreenButtonServices, } from '@kbn/shared-ux-button-exit-full-screen-types'; +import { of } from 'rxjs'; /** * Return a Jest mock of the services for the `ExitFullScreenButton` component. @@ -17,6 +18,7 @@ import { export const getServicesMock = (): ExitFullScreenButtonServices => { return { setIsFullscreen: jest.fn(), + customBranding$: of({}), }; }; @@ -29,6 +31,9 @@ export const getKibanaDependenciesMock = (): ExitFullScreenButtonKibanaDependenc chrome: { setIsVisible: jest.fn(), }, + customBranding: { + customBranding$: of({}), + }, }, }; }; diff --git a/packages/shared-ux/button/exit_full_screen/mocks/src/storybook.ts b/packages/shared-ux/button/exit_full_screen/mocks/src/storybook.ts index a44e5425c6d88..5393b333a5f81 100644 --- a/packages/shared-ux/button/exit_full_screen/mocks/src/storybook.ts +++ b/packages/shared-ux/button/exit_full_screen/mocks/src/storybook.ts @@ -12,6 +12,7 @@ import type { ExitFullScreenButtonProps as Props, ExitFullScreenButtonServices, } from '@kbn/shared-ux-button-exit-full-screen-types'; +import { of } from 'rxjs'; type PropArguments = Pick; @@ -51,6 +52,7 @@ export class StorybookMock extends AbstractStorybookMock< setIsFullscreen: (isFullscreen: boolean) => { action('setIsFullscreen')(isFullscreen); }, + customBranding$: of({}), }; } } diff --git a/packages/shared-ux/button/exit_full_screen/types/index.d.ts b/packages/shared-ux/button/exit_full_screen/types/index.d.ts index e7a3c770e672e..fe8d22880b18d 100644 --- a/packages/shared-ux/button/exit_full_screen/types/index.d.ts +++ b/packages/shared-ux/button/exit_full_screen/types/index.d.ts @@ -7,6 +7,8 @@ */ import { MouseEventHandler, HTMLAttributes } from 'react'; +import { Observable } from 'rxjs'; +import { CustomBranding } from '@kbn/core-custom-branding-common'; /** * Abstract external services for this component. @@ -14,6 +16,8 @@ import { MouseEventHandler, HTMLAttributes } from 'react'; export interface Services { /** Function to invoke to set the application to full-screen mode */ setIsFullscreen: (isFullscreen: boolean) => void; + /** Observable that emits the value of custom branding, if set*/ + customBranding$: Observable; } /** @@ -29,6 +33,9 @@ export interface KibanaDependencies { chrome: { setIsVisible: (isVisible: boolean) => void; }; + customBranding: { + customBranding$: Observable; + }; }; } @@ -55,4 +62,6 @@ export interface ExitFullScreenButtonComponentProps extends Pick, 'className'> { /** Handler to invoke when one clicks the button. */ onClick: MouseEventHandler; + /** If set, custom logo is displayed instead of Elastic logo */ + customLogo?: string; } diff --git a/packages/shared-ux/button/exit_full_screen/types/tsconfig.json b/packages/shared-ux/button/exit_full_screen/types/tsconfig.json index 362cc9e727b9f..9909bbb0564ca 100644 --- a/packages/shared-ux/button/exit_full_screen/types/tsconfig.json +++ b/packages/shared-ux/button/exit_full_screen/types/tsconfig.json @@ -9,5 +9,8 @@ ], "exclude": [ "target/**/*", + ], + "kbn_references": [ + "@kbn/core-custom-branding-common", ] } diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx index 3e3addaac6eee..e370945d58f4f 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/dashboard_container.tsx @@ -120,6 +120,7 @@ export class DashboardContainer extends Container - + diff --git a/src/plugins/dashboard/public/services/custom_branding/custom_branding.stub.ts b/src/plugins/dashboard/public/services/custom_branding/custom_branding.stub.ts index 5496c29b760f9..5db0f72e2cd6b 100644 --- a/src/plugins/dashboard/public/services/custom_branding/custom_branding.stub.ts +++ b/src/plugins/dashboard/public/services/custom_branding/custom_branding.stub.ts @@ -16,5 +16,6 @@ export const customBrandingServiceFactory: CustomBrandingServiceFactory = () => const pluginMock = coreMock.createStart(); return { hasCustomBranding$: pluginMock.customBranding.hasCustomBranding$, + customBranding$: pluginMock.customBranding.customBranding$, }; }; diff --git a/src/plugins/dashboard/public/services/custom_branding/custom_branding_service.ts b/src/plugins/dashboard/public/services/custom_branding/custom_branding_service.ts index 659a669a5bda1..c02aeedde2ad5 100644 --- a/src/plugins/dashboard/public/services/custom_branding/custom_branding_service.ts +++ b/src/plugins/dashboard/public/services/custom_branding/custom_branding_service.ts @@ -19,5 +19,6 @@ export const customBrandingServiceFactory: CustomBrandingServiceFactory = ({ cor const { customBranding } = coreStart; return { hasCustomBranding$: customBranding.hasCustomBranding$, + customBranding$: customBranding.customBranding$, }; }; diff --git a/src/plugins/dashboard/public/services/custom_branding/types.ts b/src/plugins/dashboard/public/services/custom_branding/types.ts index 7e7e88bb15a7a..3f5536d21ddcb 100644 --- a/src/plugins/dashboard/public/services/custom_branding/types.ts +++ b/src/plugins/dashboard/public/services/custom_branding/types.ts @@ -10,4 +10,5 @@ import type { CustomBrandingStart } from '@kbn/core-custom-branding-browser'; export interface DashboardCustomBrandingService { hasCustomBranding$: CustomBrandingStart['hasCustomBranding$']; + customBranding$: CustomBrandingStart['customBranding$']; } From 9ad7ebb4ea95599c73160691fd352c94350fcf76 Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Tue, 14 Feb 2023 09:45:39 +0000 Subject: [PATCH 159/203] [APM] Add more APM paths to paths-labeller.yml (#150915) ## Summary Add more APM paths so the `team:APM` label is added to the PRs --- .github/paths-labeller.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index efc03d8942b8d..1c1b2742001b5 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -10,6 +10,10 @@ - "src/plugins/bfetch/**/*.*" - "Team:apm": - "x-pack/plugins/apm/**/*.*" + - "x-pack/test/apm_api_integration/**/*.*" + - "packages/kbn-apm-synthtrace/**/*.*" + - "packages/kbn-apm-synthtrace-client/**/*.*" + - "packages/kbn-apm-utils/**/*.*" - "Team:Fleet": - "x-pack/plugins/fleet/**/*.*" - "x-pack/test/fleet_api_integration/**/*.*" From c308b9cbdc64ae21b922d99f3fc70fe47f386e93 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 14 Feb 2023 10:54:17 +0100 Subject: [PATCH 160/203] [codeql] Add Kibana Platform Security as CODEOWNER of CodeQL files (#150976) --- .github/CODEOWNERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 24c1a523c5c09..4a810cbab7b3e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -911,6 +911,8 @@ packages/kbn-yarn-lock-validator @elastic/kibana-operations #CC# /x-pack/plugins/translations/ @elastic/kibana-localization @elastic/kibana-core # Kibana Platform Security +/.github/codeql @elastic/kibana-security +/.github/workflows/codeql.yml @elastic/kibana-security /src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security /test/interactive_setup_api_integration/ @elastic/kibana-security /test/interactive_setup_functional/ @elastic/kibana-security From 3ae7d70c803dbc091cafc5d561625893ae1afacc Mon Sep 17 00:00:00 2001 From: Wafaa Nasr Date: Tue, 14 Feb 2023 10:00:15 +0000 Subject: [PATCH 161/203] [Security Solution] Fix all rules list is not present , when user manage rules from a shared exception list (#151079) ## Summary - Addresses https://github.com/elastic/kibana/issues/150989 - Pass pagination equals to `10000` to `fetchRules` api to get all user's rules as the old [use_find_rules_in_memory.ts](https://github.com/elastic/kibana/pull/149840/files#diff-c45bbe9560f22294e32a1c0a68fe374b1e360b3df01060efed93acb9153a6e72) was removed - Adding unit tests ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../add_to_rules_table/index.test.tsx | 52 ++-- .../add_to_rules_table/index.tsx | 2 +- .../link_rule_switch/index.test.tsx | 66 ++++++ .../use_add_to_rules_table.test.tsx | 222 ++++++++++++++++++ .../use_add_to_rules_table.tsx | 5 +- 5 files changed, 328 insertions(+), 19 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.test.tsx diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.test.tsx index 4be59efe2e927..a2d78c9282fe2 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { fireEvent, render, within } from '@testing-library/react'; import { ExceptionsAddToRulesTable } from '.'; import { TestProviders } from '../../../../../common/mock'; @@ -17,23 +17,19 @@ import type { Rule } from '../../../../rule_management/logic/types'; jest.mock('../../../../rule_management/logic/use_find_rules'); describe('ExceptionsAddToRulesTable', () => { - it('it displays loading state while fetching rules', () => { + it('should display the loading state while fetching rules', () => { (useFindRules as jest.Mock).mockReturnValue({ data: { rules: [], total: 0 }, isFetched: false, }); - const wrapper = mountWithIntl( - - - + const wrapper = render( + ); - expect( - wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-loading"]').exists() - ).toBeTruthy(); + expect(wrapper.getByTestId('exceptionItemViewerEmptyPromptsLoading')).toBeInTheDocument(); }); - it.skip('it displays fetched rules', () => { + it('should display the fetched rule selected', () => { (useFindRules as jest.Mock).mockReturnValue({ data: { rules: [getRulesSchemaMock(), { ...getRulesSchemaMock(), id: '345', name: 'My rule' }], @@ -41,7 +37,7 @@ describe('ExceptionsAddToRulesTable', () => { }, isFetched: true, }); - const wrapper = mountWithIntl( + const wrapper = render( { /> ); + expect(wrapper.queryByTestId('exceptionItemViewerEmptyPromptsLoading')).toBeFalsy(); + const selectedRow = wrapper.getByText('My rule').closest('tr') as HTMLTableRowElement; + const selectedSwitch = within(selectedRow).getByRole('switch'); + expect(selectedSwitch).toBeChecked(); + }); - expect( - wrapper.find('[data-test-subj="exceptionItemViewerEmptyPrompts-loading"]').exists() - ).toBeFalsy(); - expect( - wrapper.find('.euiTableRow-isSelected td[data-test-subj="ruleNameCell"]').text() - ).toEqual('NameMy rule'); + it('should invoke the onRuleSelectionChange when link switch is clicked', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: [getRulesSchemaMock(), { ...getRulesSchemaMock(), id: '345', name: 'My rule' }], + total: 0, + }, + isFetched: true, + }); + const onRuleSelectionChangeMock = jest.fn(); + const rule = { ...getRulesSchemaMock(), id: '345', name: 'My rule' }; + const { queryByTestId, getByText } = render( + + + + ); + expect(queryByTestId('exceptionItemViewerEmptyPromptsLoading')).toBeFalsy(); + const selectedRow = getByText('My rule').closest('tr') as HTMLTableRowElement; + const selectedSwitch = within(selectedRow).getByRole('switch'); + fireEvent.click(selectedSwitch); + expect(onRuleSelectionChangeMock).toBeCalledWith([rule]); }); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.tsx index 18434bc69dfc4..4760371ce5e81 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/index.tsx @@ -50,7 +50,7 @@ const ExceptionsAddToRulesTableComponent: React.FC ) : undefined } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.test.tsx new file mode 100644 index 0000000000000..02b199faf0e0b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/link_rule_switch/index.test.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, render } from '@testing-library/react'; +import { getRulesSchemaMock } from '../../../../../../../common/detection_engine/rule_schema/mocks'; + +import { LinkRuleSwitch } from '.'; + +const mockedRule = getRulesSchemaMock(); +const linkedRules = Array(3).fill(mockedRule); +const onRuleLinkChangeMock = jest.fn(); +describe('LinkRuleSwitch', () => { + it('should render the switch checked if rule is linked', () => { + const { getByRole } = render( + + ); + const switchComponent = getByRole('switch'); + expect(switchComponent).toBeChecked(); + }); + it('should render the switch unchecked if rule is unlinked', () => { + const { getByRole } = render( + + ); + const switchComponent = getByRole('switch'); + expect(switchComponent).not.toBeChecked(); + }); + it('should link rule if not linked before', () => { + const { getByRole } = render( + + ); + const switchComponent = getByRole('switch'); + expect(switchComponent).not.toBeChecked(); + fireEvent.click(switchComponent); + expect(onRuleLinkChangeMock).toBeCalledWith([linkedRules[0]]); + }); + it('should unlink rule if it was linked before', () => { + const { getByRole } = render( + + ); + const switchComponent = getByRole('switch'); + expect(switchComponent).toBeChecked(); + fireEvent.click(switchComponent); + expect(onRuleLinkChangeMock).toBeCalledWith([]); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.test.tsx new file mode 100644 index 0000000000000..787b34857520b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.test.tsx @@ -0,0 +1,222 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, render as rTLRender } from '@testing-library/react'; +import { waitFor } from '@testing-library/dom'; +import { act, renderHook } from '@testing-library/react-hooks'; +import type { EuiTableFieldDataColumnType } from '@elastic/eui'; +import type { Rule } from '../../../../rule_management/logic/types'; +import { getRulesSchemaMock } from '../../../../../../common/detection_engine/rule_schema/mocks'; +import { useFindRules } from '../../../../rule_management/logic/use_find_rules'; +import { useAddToRulesTable } from './use_add_to_rules_table'; + +jest.mock('../../../../rule_management/logic/use_find_rules'); + +const mockedRule = getRulesSchemaMock(); +const onRuleSelectionChangeMock = jest.fn(); +const initiallySelectedRules = [{ ...mockedRule, id: '345', name: 'My rule' }] as Rule[]; + +describe('useAddToRulesTable', () => { + it('should call the useFindRules with the correct parameters', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: [mockedRule], + total: 0, + }, + isFetched: true, + }); + renderHook(() => + useAddToRulesTable({ + initiallySelectedRules, + onRuleSelectionChange: onRuleSelectionChangeMock, + }) + ); + expect(useFindRules as jest.Mock).toBeCalledWith({ + filterOptions: { + filter: '', + showCustomRules: false, + showElasticRules: false, + tags: [], + }, + sortingOptions: undefined, + pagination: { + page: 1, + perPage: 10000, + }, + }); + }); + it('should return all stored rule if less than 10000 when calling the useFindRules', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: Array(30).fill(mockedRule), + total: 0, + }, + isFetched: true, + }); + const { + result: { current }, + } = renderHook(() => + useAddToRulesTable({ + initiallySelectedRules, + onRuleSelectionChange: onRuleSelectionChangeMock, + }) + ); + const { sortedRulesByLinkedRulesOnTop, isLoading } = current; + expect(sortedRulesByLinkedRulesOnTop.length).toEqual(30); + expect(isLoading).toBeFalsy(); + }); + it('should return isLoading true and pagination as default if useFindRules is fetching', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: [], + total: 0, + }, + isFetched: false, + }); + const { + result: { current }, + } = renderHook(() => + useAddToRulesTable({ + initiallySelectedRules, + onRuleSelectionChange: onRuleSelectionChangeMock, + }) + ); + const { + sortedRulesByLinkedRulesOnTop, + isLoading, + pagination, + searchOptions, + addToSelectedRulesDescription, + } = current; + expect(sortedRulesByLinkedRulesOnTop.length).toEqual(0); + expect(isLoading).toBeTruthy(); + expect(pagination).toEqual({ pageIndex: 0, initialPageSize: 5, showPerPageOptions: false }); + expect(searchOptions.filters[0].name).toEqual('Tags'); + expect(addToSelectedRulesDescription).toEqual( + 'After you create the exception, it is added to the rules you link. ' + ); + }); + it('should sort initially selected rules on top', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: [mockedRule, { ...mockedRule, id: '345', name: 'My rule' }], + total: 0, + }, + isFetched: true, + }); + const { + result: { current }, + } = renderHook(() => + useAddToRulesTable({ + initiallySelectedRules, + onRuleSelectionChange: onRuleSelectionChangeMock, + }) + ); + const { sortedRulesByLinkedRulesOnTop } = current; + expect(sortedRulesByLinkedRulesOnTop[0]).toEqual( + expect.objectContaining({ id: '345', name: 'My rule' }) + ); + }); + it('should filter out duplicated tags from tag options', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: [ + { ...mockedRule, tags: ['some fake tag 1'] }, + { ...mockedRule, tags: ['some fake tag 1'], id: '345', name: 'My rule' }, + ], + total: 0, + }, + isFetched: true, + }); + const { + result: { current }, + } = renderHook(() => + useAddToRulesTable({ + initiallySelectedRules, + onRuleSelectionChange: onRuleSelectionChangeMock, + }) + ); + const { searchOptions } = current; + const { filters } = searchOptions; + const { options } = filters[0]; + expect(options).toEqual([ + { + name: 'some fake tag 1', + value: 'some fake tag 1', + }, + ]); + }); + it('should call onRuleLinkChange when switch of a rule is clicked', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: [ + mockedRule, + { ...mockedRule, tags: ['some fake tag 1'], id: '345', name: 'My rule' }, + ], + total: 0, + }, + isFetched: true, + }); + + const { + result: { current }, + } = renderHook(() => + useAddToRulesTable({ + initiallySelectedRules, + onRuleSelectionChange: onRuleSelectionChangeMock, + }) + ); + const { rulesTableColumnsWithLinkSwitch } = current; + const { name, render } = + rulesTableColumnsWithLinkSwitch[0] as EuiTableFieldDataColumnType; + expect(name).toEqual('Link'); + + const LinkColumn = (render ? render(null, mockedRule as Rule) : <>) as JSX.Element; + const { getByRole } = rTLRender(

{LinkColumn}
); + const selectedSwitch = getByRole('switch'); + fireEvent.click(selectedSwitch); + + expect(onRuleSelectionChangeMock).toBeCalledWith([ + expect.objectContaining({ id: '345', name: 'My rule' }), + ]); + }); + it('should change the pagination when onTableChange is called', () => { + (useFindRules as jest.Mock).mockReturnValue({ + data: { + rules: [ + mockedRule, + { ...mockedRule, tags: ['some fake tag 1'], id: '345', name: 'My rule' }, + ], + total: 0, + }, + isFetched: true, + }); + + const { + result: { current }, + } = renderHook(() => + useAddToRulesTable({ + initiallySelectedRules, + onRuleSelectionChange: onRuleSelectionChangeMock, + }) + ); + + const { onTableChange, pagination } = current; + act(() => { + onTableChange({ page: { index: 2, size: 10 } }); + }); + waitFor(() => + expect(pagination).toEqual({ + initialPageSize: 5, + pageIndex: 2, + size: 10, + showPerPageOptions: false, + }) + ); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.tsx index e18cc71802c31..529689e3cd343 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_exceptions/components/flyout_components/add_to_rules_table/use_add_to_rules_table.tsx @@ -36,7 +36,10 @@ export const useAddToRulesTable = ({ tags: [], }, sortingOptions: undefined, - pagination: undefined, + pagination: { + page: 1, + perPage: 10000, + }, }); const [pagination, setPagination] = useState({ From 6e58c2dba5d2e09214ee84c11c2011d1a2b23092 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 14 Feb 2023 12:20:09 +0100 Subject: [PATCH 162/203] [AO] Reuse overview bucket size in AlertSummaryWidget (#150453) Resolves #150290 ## Summary - Reuse the overview bucket size in AlertSummaryWidget. - Use `scaled date format` setting instead of `niceTimeFormatter` in observability overview charts Before ![image](https://user-images.githubusercontent.com/12370520/217490029-06fa183e-c2f2-4d86-a09d-bde77ac45e07.png) After ![image](https://user-images.githubusercontent.com/12370520/217492571-207c27eb-e7a0-4d90-998f-7f79beca4c02.png) --- .../components/app/section/apm/index.test.tsx | 8 ++- .../components/app/section/apm/index.tsx | 5 +- .../components/app/section/logs/index.tsx | 5 +- .../components/app/section/uptime/index.tsx | 5 +- .../components/app/section/ux/index.test.tsx | 10 ++-- .../containers/alerts_page/alerts_page.tsx | 21 ++++++- .../containers/overview_page/constants.ts | 3 + .../helpers/calculate_bucket_size.test.ts | 55 +++++++++++++++++++ .../helpers/calculate_bucket_size.ts | 29 +++++++++- .../overview_page/overview_page.tsx | 31 +++++++---- .../containers/overview_page/types.ts | 7 ++- .../get_alert_summary_time_range.test.tsx | 41 +++----------- .../get_alert_summary_time_range.tsx | 22 ++------ 13 files changed, 162 insertions(+), 80 deletions(-) create mode 100644 x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/calculate_bucket_size.test.ts diff --git a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx index 509d8726f2ddc..0fc62d4066604 100644 --- a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx +++ b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx @@ -28,6 +28,8 @@ jest.mock('react-router-dom', () => ({ })); describe('APMSection', () => { + const bucketSize = { intervalString: '60s', bucketSize: 60, dateFormat: 'YYYY-MM-DD HH:mm' }; + beforeAll(() => { jest.spyOn(hasDataHook, 'useHasData').mockReturnValue({ hasDataMap: { @@ -81,7 +83,7 @@ describe('APMSection', () => { refetch: jest.fn(), }); const { getByRole, getByText, queryAllByTestId } = render( - + ); expect(getByRole('heading')).toHaveTextContent('Services'); @@ -98,7 +100,7 @@ describe('APMSection', () => { refetch: jest.fn(), }); const { getByRole, getByText, queryAllByTestId } = render( - + ); expect(getByRole('heading')).toHaveTextContent('Services'); @@ -114,7 +116,7 @@ describe('APMSection', () => { refetch: jest.fn(), }); const { getByRole, queryAllByText, getByTestId } = render( - + ); expect(getByRole('heading')).toHaveTextContent('Services'); diff --git a/x-pack/plugins/observability/public/components/app/section/apm/index.tsx b/x-pack/plugins/observability/public/components/app/section/apm/index.tsx index 860e134442ccb..a8d7aafcbaef4 100644 --- a/x-pack/plugins/observability/public/components/app/section/apm/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/apm/index.tsx @@ -14,6 +14,7 @@ import { Settings, XYBrushEvent, } from '@elastic/charts'; +import { timeFormatter } from '@elastic/charts/dist/utils/data/formatters'; import { EuiFlexGroup, EuiFlexItem, EuiToolTip, EuiIcon } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; @@ -85,7 +86,9 @@ export function APMSection({ bucketSize }: Props) { const min = moment.utc(absoluteStart).valueOf(); const max = moment.utc(absoluteEnd).valueOf(); - const formatter = niceTimeFormatter([min, max]); + const formatter = bucketSize?.dateFormat + ? timeFormatter(bucketSize?.dateFormat) + : niceTimeFormatter([min, max]); const isLoading = status === FETCH_STATUS.LOADING; diff --git a/x-pack/plugins/observability/public/components/app/section/logs/index.tsx b/x-pack/plugins/observability/public/components/app/section/logs/index.tsx index b047d5f7f8925..c8538c5582683 100644 --- a/x-pack/plugins/observability/public/components/app/section/logs/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/logs/index.tsx @@ -14,6 +14,7 @@ import { Settings, XYBrushEvent, } from '@elastic/charts'; +import { timeFormatter } from '@elastic/charts/dist/utils/data/formatters'; import { EuiFlexGroup, EuiFlexItem, euiPaletteColorBlind, EuiSpacer, EuiTitle } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; @@ -83,7 +84,9 @@ export function LogsSection({ bucketSize }: Props) { const min = moment.utc(absoluteStart).valueOf(); const max = moment.utc(absoluteEnd).valueOf(); - const formatter = niceTimeFormatter([min, max]); + const formatter = bucketSize?.dateFormat + ? timeFormatter(bucketSize?.dateFormat) + : niceTimeFormatter([min, max]); const { appLink, stats, series } = data || {}; diff --git a/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx b/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx index 637f39eeedd68..04f23fd5a4baf 100644 --- a/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx @@ -15,6 +15,7 @@ import { TickFormatter, XYBrushEvent, } from '@elastic/charts'; +import { timeFormatter } from '@elastic/charts/dist/utils/data/formatters'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; @@ -81,7 +82,9 @@ export function UptimeSection({ bucketSize }: Props) { const min = moment.utc(absoluteStart).valueOf(); const max = moment.utc(absoluteEnd).valueOf(); - const formatter = niceTimeFormatter([min, max]); + const formatter = bucketSize?.dateFormat + ? timeFormatter(bucketSize?.dateFormat) + : niceTimeFormatter([min, max]); const isLoading = status === FETCH_STATUS.LOADING; diff --git a/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx index c8f508a366bea..5d572f4f16207 100644 --- a/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx +++ b/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx @@ -21,6 +21,8 @@ jest.mock('react-router-dom', () => ({ })); describe('UXSection', () => { + const bucketSize = { intervalString: '60s', bucketSize: 60, dateFormat: 'YYYY-MM-DD HH:mm' }; + beforeAll(() => { jest.spyOn(hasDataHook, 'useHasData').mockReturnValue({ hasDataMap: { @@ -44,9 +46,7 @@ describe('UXSection', () => { status: fetcherHook.FETCH_STATUS.SUCCESS, refetch: jest.fn(), }); - const { getByText, getAllByText } = render( - - ); + const { getByText, getAllByText } = render(); expect(getByText('User Experience')).toBeInTheDocument(); expect(getByText('Show dashboard')).toBeInTheDocument(); @@ -79,7 +79,7 @@ describe('UXSection', () => { refetch: jest.fn(), }); const { getByText, queryAllByText, getAllByText } = render( - + ); expect(getByText('User Experience')).toBeInTheDocument(); @@ -94,7 +94,7 @@ describe('UXSection', () => { refetch: jest.fn(), }); const { getByText, queryAllByText, getAllByText } = render( - + ); expect(getByText('User Experience')).toBeInTheDocument(); 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 ece685f8ce680..4eb7aabc66202 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 @@ -12,6 +12,11 @@ import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; import { AlertConsumers } from '@kbn/rule-data-utils'; +import { calculateTimeRangeBucketSize } from '../../../overview/containers/overview_page/helpers/calculate_bucket_size'; +import { + DEFAULT_DATE_FORMAT, + DEFAULT_INTERVAL, +} from '../../../overview/containers/overview_page/constants'; import { useToasts } from '../../../../hooks/use_toast'; import { alertSearchBarStateContainer, @@ -77,9 +82,9 @@ function InternalAlertsPage() { const { hasAnyData, isAllRequestsComplete } = useHasData(); const [esQuery, setEsQuery] = useState<{ bool: BoolQuery }>(); const timeBuckets = useTimeBuckets(); - const alertSummaryTimeRange = useMemo( + const bucketSize = useMemo( () => - getAlertSummaryTimeRange( + calculateTimeRangeBucketSize( { from: alertSearchBarStateProps.rangeFrom, to: alertSearchBarStateProps.rangeTo, @@ -88,6 +93,18 @@ function InternalAlertsPage() { ), [alertSearchBarStateProps.rangeFrom, alertSearchBarStateProps.rangeTo, timeBuckets] ); + const alertSummaryTimeRange = useMemo( + () => + getAlertSummaryTimeRange( + { + from: alertSearchBarStateProps.rangeFrom, + to: alertSearchBarStateProps.rangeTo, + }, + bucketSize?.intervalString || DEFAULT_INTERVAL, + bucketSize?.dateFormat || DEFAULT_DATE_FORMAT + ), + [alertSearchBarStateProps.rangeFrom, alertSearchBarStateProps.rangeTo, bucketSize] + ); useBreadcrumbs([ { 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 cca2bb765e719..d394e5aa53b3e 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,6 +7,9 @@ export const CAPABILITIES_KEYS = ['logs', 'infrastructure', 'apm', 'uptime']; +export const DEFAULT_INTERVAL = '60s'; +export const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm'; + 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/helpers/calculate_bucket_size.test.ts b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/calculate_bucket_size.test.ts new file mode 100644 index 0000000000000..1b936903ef133 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/calculate_bucket_size.test.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TimeBuckets } from '@kbn/data-plugin/common'; +import { calculateTimeRangeBucketSize } from './calculate_bucket_size'; + +describe('calculateTimeRangeBucketSize', () => { + const timeBucketConfig = { + 'histogram:maxBars': 4, + 'histogram:barTarget': 3, + dateFormat: 'YYYY-MM-DD', + 'dateFormat:scaled': [ + ['', 'HH:mm:ss.SSS'], + ['PT1S', 'HH:mm:ss'], + ['PT1M', 'HH:mm'], + ['PT1H', 'YYYY-MM-DD HH:mm'], + ['P1DT', 'YYYY-MM-DD'], + ['P1YT', 'YYYY'], + ], + }; + const timeBuckets = new TimeBuckets(timeBucketConfig); + + it.each([ + // 15 minutes + ['2023-01-09T12:07:54.441Z', '2023-01-09T12:22:54.441Z', 60, '60s', 'HH:mm'], + ['now-15m', 'now', 60, '60s', 'HH:mm'], + // 30 minutes + ['2023-01-09T11:53:43.605Z', '2023-01-09T12:23:43.605Z', 60, '60s', 'HH:mm'], + // 1 hour + ['2023-01-09T11:22:05.728Z', '2023-01-09T12:22:05.728Z', 60, '60s', 'HH:mm'], + // 24 hours + ['2023-01-08T12:00:00.000Z', '2023-01-09T12:24:30.853Z', 600, '600s', 'HH:mm'], + // 7 days + ['2023-01-01T23:00:00.000Z', '2023-01-09T12:29:38.101Z', 3600, '3600s', 'YYYY-MM-DD HH:mm'], + // 30 days + ['2022-12-09T23:00:00.000Z', '2023-01-09T12:30:13.717Z', 43200, '43200s', 'YYYY-MM-DD HH:mm'], + // 90 days + ['2022-10-10T22:00:00.000Z', '2023-01-09T12:32:11.537Z', 43200, '43200s', 'YYYY-MM-DD HH:mm'], + // 1 year + ['2022-01-08T23:00:00.000Z', '2023-01-09T12:33:09.906Z', 86400, '86400s', 'YYYY-MM-DD'], + ])( + `Input: [%s, %s], Output: bucketSize: %s, intervalString: %s, dateFormat: %s `, + (from, to, bucketSize, intervalString, dateFormat) => { + expect(calculateTimeRangeBucketSize({ from, to }, timeBuckets)).toEqual({ + bucketSize, + intervalString, + dateFormat, + }); + } + ); +}); diff --git a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/calculate_bucket_size.ts b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/calculate_bucket_size.ts index 5a2f8650baccc..c188aab6160fa 100644 --- a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/calculate_bucket_size.ts +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/calculate_bucket_size.ts @@ -5,11 +5,36 @@ * 2.0. */ +import { TimeBuckets } from '@kbn/data-plugin/common'; +import { TimeRange } from '@kbn/es-query'; +import { getAbsoluteTime } from '../../../../../utils/date'; +import { DEFAULT_INTERVAL } from '../constants'; import { Bucket, BucketSize } from '../types'; import { getBucketSize } from '../../../../../utils/get_bucket_size'; -export function calculateBucketSize({ start, end }: Bucket): BucketSize { +export function calculateBucketSize({ start, end, timeBuckets }: Bucket): BucketSize { if (start && end) { - return getBucketSize({ start, end, minInterval: '60s' }); + const { bucketSize, intervalString } = getBucketSize({ + start, + end, + minInterval: DEFAULT_INTERVAL, + }); + timeBuckets.setInterval(intervalString); + + return { + bucketSize, + intervalString, + dateFormat: timeBuckets.getScaledDateFormat(), + }; } } + +export function calculateTimeRangeBucketSize( + { from, to }: TimeRange, + timeBuckets: TimeBuckets +): BucketSize { + const start = getAbsoluteTime(from); + const end = getAbsoluteTime(to, { roundUp: true }); + + return calculateBucketSize({ start, end, timeBuckets }); +} 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 b155c2927ee92..50d4befaefa56 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 @@ -39,7 +39,12 @@ import { getNewsFeed } from '../../../../services/get_news_feed'; import { buildEsQuery } from '../../../../utils/build_es_query'; import { getAlertSummaryTimeRange } from '../../../../utils/alert_summary_widget'; -import { ALERTS_PER_PAGE, ALERTS_TABLE_ID } from './constants'; +import { + ALERTS_PER_PAGE, + ALERTS_TABLE_ID, + DEFAULT_DATE_FORMAT, + DEFAULT_INTERVAL, +} from './constants'; import { calculateBucketSize, useOverviewMetrics } from './helpers'; export function OverviewPage() { @@ -91,7 +96,17 @@ export function OverviewPage() { to: relativeEnd, }) ); + const timeBuckets = useTimeBuckets(); + const bucketSize = useMemo( + () => + calculateBucketSize({ + start: absoluteStart, + end: absoluteEnd, + timeBuckets, + }), + [absoluteStart, absoluteEnd, timeBuckets] + ); const alertSummaryTimeRange = useMemo( () => getAlertSummaryTimeRange( @@ -99,9 +114,10 @@ export function OverviewPage() { from: relativeStart, to: relativeEnd, }, - timeBuckets + bucketSize?.intervalString || DEFAULT_INTERVAL, + bucketSize?.dateFormat || DEFAULT_DATE_FORMAT ), - [relativeEnd, relativeStart, timeBuckets] + [bucketSize, relativeEnd, relativeStart] ); const chartThemes = { @@ -109,15 +125,6 @@ export function OverviewPage() { baseTheme: charts.theme.useChartsBaseTheme(), }; - const bucketSize = useMemo( - () => - calculateBucketSize({ - start: absoluteStart, - end: absoluteEnd, - }), - [absoluteStart, absoluteEnd] - ); - useEffect(() => { setEsQuery( buildEsQuery({ diff --git a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/types.ts b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/types.ts index 95b0a4f1491a0..7d66709025480 100644 --- a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/types.ts +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/types.ts @@ -5,8 +5,13 @@ * 2.0. */ +import { TimeBuckets } from '@kbn/data-plugin/common'; + export interface Bucket { start?: number; end?: number; + timeBuckets: TimeBuckets; } -export type BucketSize = { bucketSize: number; intervalString: string } | undefined; +export type BucketSize = + | { bucketSize: number; intervalString: string; dateFormat: string } + | undefined; diff --git a/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.test.tsx b/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.test.tsx index d63cce34755c1..f961d918632ef 100644 --- a/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.test.tsx +++ b/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.test.tsx @@ -6,14 +6,13 @@ */ import moment from 'moment'; -import { TimeBuckets } from '@kbn/data-plugin/common'; import { getAlertSummaryTimeRange, getDefaultAlertSummaryTimeRange } from '.'; describe('AlertSummaryTimeRange', () => { describe('getDefaultAlertSummaryTimeRange', () => { it('should return default time in UTC format', () => { - const defaultTimeRange = getDefaultAlertSummaryTimeRange(); const utcFormat = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; + const defaultTimeRange = getDefaultAlertSummaryTimeRange(); expect(moment(defaultTimeRange.utcFrom, utcFormat, true).isValid()).toBeTruthy(); expect(moment(defaultTimeRange.utcTo, utcFormat, true).isValid()).toBeTruthy(); @@ -21,44 +20,18 @@ describe('AlertSummaryTimeRange', () => { }); describe('getAlertSummaryTimeRange', () => { - const timeBucketConfig = { - 'histogram:maxBars': 4, - 'histogram:barTarget': 3, - dateFormat: 'YYYY-MM-DD', - 'dateFormat:scaled': [ - ['', 'HH:mm:ss.SSS'], - ['PT1S', 'HH:mm:ss'], - ['PT1M', 'HH:mm'], - ['PT1H', 'YYYY-MM-DD HH:mm'], - ['P1DT', 'YYYY-MM-DD'], - ['P1YT', 'YYYY'], - ], - }; - const timeBuckets = new TimeBuckets(timeBucketConfig); + const utcRegex = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}Z/; it.each([ // 15 minutes ['2023-01-09T12:07:54.441Z', '2023-01-09T12:22:54.441Z', '30s', 'HH:mm:ss'], - // 30 minutes - ['2023-01-09T11:53:43.605Z', '2023-01-09T12:23:43.605Z', '30s', 'HH:mm:ss'], - // 1 hour - ['2023-01-09T11:22:05.728Z', '2023-01-09T12:22:05.728Z', '60s', 'HH:mm'], - // 24 hours - ['2023-01-08T12:00:00.000Z', '2023-01-09T12:24:30.853Z', '1800s', 'HH:mm'], - // 7 days - ['2023-01-01T23:00:00.000Z', '2023-01-09T12:29:38.101Z', '10800s', 'YYYY-MM-DD HH:mm'], - // 30 days - ['2022-12-09T23:00:00.000Z', '2023-01-09T12:30:13.717Z', '43200s', 'YYYY-MM-DD HH:mm'], - // 90 days - ['2022-10-10T22:00:00.000Z', '2023-01-09T12:32:11.537Z', '86400s', 'YYYY-MM-DD'], - // 1 year - ['2022-01-08T23:00:00.000Z', '2023-01-09T12:33:09.906Z', '86400s', 'YYYY-MM-DD'], + ['now-15m', 'now', '30s', 'HH:mm:ss'], ])( - `Input: [%s, %s], Output: interval: %s, time format: %s `, + `Input: [%s, %s, %s, %s] should return dates in UTC format`, (from, to, fixedInterval, dateFormat) => { - expect(getAlertSummaryTimeRange({ from, to }, timeBuckets)).toEqual({ - utcFrom: from, - utcTo: to, + expect(getAlertSummaryTimeRange({ from, to }, fixedInterval, dateFormat)).toMatchObject({ + utcFrom: expect.stringMatching(new RegExp(utcRegex)), + utcTo: expect.stringMatching(new RegExp(utcRegex)), fixedInterval, dateFormat, }); diff --git a/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.tsx b/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.tsx index a39388391278f..e0a95411a50a2 100644 --- a/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.tsx +++ b/x-pack/plugins/observability/public/utils/alert_summary_widget/get_alert_summary_time_range.tsx @@ -6,12 +6,10 @@ */ import React from 'react'; -import { getAbsoluteTimeRange, TimeBuckets } from '@kbn/data-plugin/common'; +import { getAbsoluteTimeRange } from '@kbn/data-plugin/common'; import { TimeRange } from '@kbn/es-query'; import { FormattedMessage } from '@kbn/i18n-react'; import type { AlertSummaryTimeRange } from '@kbn/triggers-actions-ui-plugin/public'; -import { getAbsoluteTime } from '../date'; -import { getBucketSize } from '../get_bucket_size'; export const getDefaultAlertSummaryTimeRange = (): AlertSummaryTimeRange => { const { to, from } = getAbsoluteTimeRange({ @@ -34,27 +32,15 @@ export const getDefaultAlertSummaryTimeRange = (): AlertSummaryTimeRange => { export const getAlertSummaryTimeRange = ( timeRange: TimeRange, - timeBuckets: TimeBuckets + fixedInterval: string, + dateFormat: string ): AlertSummaryTimeRange => { const { to, from } = getAbsoluteTimeRange(timeRange); - const fixedInterval = getFixedInterval(timeRange); - timeBuckets.setInterval(fixedInterval); return { utcFrom: from, utcTo: to, fixedInterval, - dateFormat: timeBuckets.getScaledDateFormat(), + dateFormat, }; }; - -const getFixedInterval = ({ from, to }: TimeRange) => { - const start = getAbsoluteTime(from); - const end = getAbsoluteTime(to, { roundUp: true }); - - if (start && end) { - return getBucketSize({ start, end, minInterval: '30s', buckets: 60 }).intervalString; - } - - return '1m'; -}; From 668fe89e82db05fedb9a7b8c0b3bd4a61f91909b Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Tue, 14 Feb 2023 12:54:40 +0100 Subject: [PATCH 163/203] [Discover] Suppress "Missing index" toasts (#149625) Closes #129020 Screenshot 2023-01-27 at 16 56 16 --------- Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: Matthew Kime --- .../common/data_views/data_views.test.ts | 41 ++++++++++++++++- .../common/data_views/data_views.ts | 45 +++++++++++++------ .../main/components/no_results/no_results.tsx | 4 +- .../no_results_suggestion_default.tsx | 35 ++++++++++++--- .../no_results_suggestions.tsx | 2 +- .../use_fetch_occurances_range.ts | 43 +++++++++--------- .../application/main/discover_main_route.tsx | 7 ++- .../main/hooks/utils/change_data_view.ts | 9 +++- .../main/utils/resolve_data_view.ts | 19 +++++--- .../public/hooks/use_existing_fields.ts | 10 +++-- .../public/hooks/use_grouped_fields.ts | 10 ++++- .../dataview_picker/change_dataview.tsx | 9 +++- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 15 files changed, 174 insertions(+), 63 deletions(-) diff --git a/src/plugins/data_views/common/data_views/data_views.test.ts b/src/plugins/data_views/common/data_views/data_views.test.ts index 6f54cac9041a0..b382827d5d37a 100644 --- a/src/plugins/data_views/common/data_views/data_views.test.ts +++ b/src/plugins/data_views/common/data_views/data_views.test.ts @@ -420,7 +420,7 @@ describe('IndexPatterns', () => { describe('getDefaultDataView', () => { beforeEach(() => { indexPatterns.clearCache(); - jest.resetAllMocks(); + jest.clearAllMocks(); }); test('gets default data view', async () => { @@ -434,6 +434,44 @@ describe('IndexPatterns', () => { expect(savedObjectsClient.find).toBeCalledTimes(1); }); + test('gets default data view and passes down defined arguments (refreshFields and displayErrors)', async () => { + uiSettings.get = jest.fn().mockResolvedValue(indexPatternObj.id); + savedObjectsClient.get = jest.fn().mockResolvedValue(indexPatternObj); + savedObjectsClient.find = jest.fn().mockResolvedValue([indexPatternObj]); + jest.spyOn(indexPatterns, 'get'); + jest.spyOn(indexPatterns, 'refreshFields'); + + const dataView = await indexPatterns.get(indexPatternObj.id); // and to cache the result + + const refreshFields = true; + const displayErrors = false; + expect( + await indexPatterns.getDefaultDataView({ refreshFields, displayErrors }) + ).toBeInstanceOf(DataView); + expect(savedObjectsClient.get).toBeCalledTimes(1); + expect(savedObjectsClient.find).toBeCalledTimes(1); + + expect(indexPatterns.get).toBeCalledWith(indexPatternObj.id, displayErrors, refreshFields); + expect(indexPatterns.refreshFields).toBeCalledWith(dataView, displayErrors); + }); + + test('gets default data view and passes down undefined arguments (refreshFields and displayErrors)', async () => { + uiSettings.get = jest.fn().mockResolvedValue(indexPatternObj.id); + savedObjectsClient.get = jest.fn().mockResolvedValue(indexPatternObj); + savedObjectsClient.find = jest.fn().mockResolvedValue([indexPatternObj]); + jest.spyOn(indexPatterns, 'get'); + jest.spyOn(indexPatterns, 'refreshFields'); + + await indexPatterns.get(indexPatternObj.id); // to cache the result + + expect(await indexPatterns.getDefaultDataView()).toBeInstanceOf(DataView); + expect(savedObjectsClient.get).toBeCalledTimes(1); + expect(savedObjectsClient.find).toBeCalledTimes(1); + + expect(indexPatterns.get).toBeCalledWith(indexPatternObj.id, true, undefined); + expect(indexPatterns.refreshFields).not.toBeCalled(); + }); + test('returns undefined if no data views exist', async () => { uiSettings.get = jest.fn().mockResolvedValue('foo'); savedObjectsClient.find = jest.fn().mockResolvedValue([]); @@ -487,6 +525,7 @@ describe('IndexPatterns', () => { }); test('dont set defaultIndex without capability allowing advancedSettings save', async () => { + uiSettings.get = jest.fn().mockResolvedValue(null); savedObjectsClient.find = jest.fn().mockResolvedValue([ { id: 'id1', 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 af40e4137f75f..65d23292486f3 100644 --- a/src/plugins/data_views/common/data_views/data_views.ts +++ b/src/plugins/data_views/common/data_views/data_views.ts @@ -214,9 +214,14 @@ export interface DataViewsServicePublicMethods { getDefaultId: () => Promise; /** * Get default data view, if it doesn't exist, choose and save new default data view and return it. - * @param refreshFields - refresh field list when true + * @param {Object} options + * @param {boolean} options.refreshFields - If true, will refresh the fields of the default data view + * @param {boolean} [options.displayErrors=true] - If set false, API consumer is responsible for displaying and handling errors. */ - getDefaultDataView: (refreshFields?: boolean) => Promise; + getDefaultDataView: (options?: { + refreshFields?: boolean; + displayErrors?: boolean; + }) => Promise; /** * Get fields for data view * @param dataView - Data view instance or spec @@ -259,7 +264,6 @@ export interface DataViewsServicePublicMethods { /** * Converts data view saved object to spec * @params savedObject - Data view saved object - * @params displayErrors - If set false, API consumer is responsible for displaying and handling errors. */ savedObjectToSpec: (savedObject: SavedObject) => DataViewSpec; /** @@ -610,7 +614,8 @@ export class DataViewsService { id: string, title: string, options: GetFieldsOptions, - fieldAttrs: FieldAttrs = {} + fieldAttrs: FieldAttrs = {}, + displayErrors: boolean = true ) => { const fieldsAsArr = Object.values(fields); const scriptedFields = fieldsAsArr.filter((field) => field.scripted); @@ -630,10 +635,12 @@ export class DataViewsService { return { fields: this.fieldArrayToMap(updatedFieldList, fieldAttrs), indices }; } catch (err) { if (err instanceof DataViewMissingIndices) { - this.onNotification( - { title: err.message, color: 'danger', iconType: 'alert' }, - `refreshFieldSpecMap:${title}` - ); + if (displayErrors) { + this.onNotification( + { title: err.message, color: 'danger', iconType: 'alert' }, + `refreshFieldSpecMap:${title}` + ); + } return {}; } @@ -739,9 +746,11 @@ export class DataViewsService { private initFromSavedObjectLoadFields = async ({ savedObjectId, spec, + displayErrors = true, }: { savedObjectId: string; spec: DataViewSpec; + displayErrors?: boolean; }) => { const { title, type, typeMeta, runtimeFieldMap } = spec; const { fields, indices } = await this.refreshFieldSpecMap( @@ -755,7 +764,8 @@ export class DataViewsService { rollupIndex: typeMeta?.params?.rollup_index, allowNoIndex: spec.allowNoIndex, }, - spec.fieldAttrs + spec.fieldAttrs, + displayErrors ); const runtimeFieldSpecs = this.getRuntimeFields(runtimeFieldMap, spec.fieldAttrs); @@ -779,6 +789,7 @@ export class DataViewsService { const fieldsAndIndices = await this.initFromSavedObjectLoadFields({ savedObjectId: savedObject.id, spec, + displayErrors, }); fields = fieldsAndIndices.fields; indices = fieldsAndIndices.indices; @@ -883,7 +894,7 @@ export class DataViewsService { ): Promise => { const dataViewFromCache = this.dataViewCache.get(id)?.then(async (dataView) => { if (dataView && refreshFields) { - await this.refreshFields(dataView); + await this.refreshFields(dataView, displayErrors); } return dataView; }); @@ -1144,10 +1155,18 @@ export class DataViewsService { * another data view is selected as default and returned. * If no possible data view found to become a default returns null. * - * @param {boolean} refreshFields - if true, will refresh the fields of the default data view + * @param {Object} options + * @param {boolean} options.refreshFields - If true, will refresh the fields of the default data view + * @param {boolean} [options.displayErrors=true] - If set false, API consumer is responsible for displaying and handling errors. * @returns default data view */ - async getDefaultDataView(refreshFields?: boolean): Promise { + async getDefaultDataView( + options: { + displayErrors?: boolean; + refreshFields?: boolean; + } = {} + ): Promise { + const { displayErrors = true, refreshFields } = options; const patterns = await this.getIdsWithTitle(); let defaultId: string | undefined = await this.config.get('defaultIndex'); const exists = defaultId ? patterns.some((pattern) => pattern.id === defaultId) : false; @@ -1168,7 +1187,7 @@ export class DataViewsService { } if (defaultId) { - return this.get(defaultId, undefined, refreshFields); + return this.get(defaultId, displayErrors, refreshFields); } else { return null; } diff --git a/src/plugins/discover/public/application/main/components/no_results/no_results.tsx b/src/plugins/discover/public/application/main/components/no_results/no_results.tsx index c24423693a622..3286dff4aa27d 100644 --- a/src/plugins/discover/public/application/main/components/no_results/no_results.tsx +++ b/src/plugins/discover/public/application/main/components/no_results/no_results.tsx @@ -49,8 +49,8 @@ export function DiscoverNoResults({ } color="danger" diff --git a/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestion_default.tsx b/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestion_default.tsx index b90ca64c23e64..b920727782e71 100644 --- a/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestion_default.tsx +++ b/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestion_default.tsx @@ -8,15 +8,36 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiText } from '@elastic/eui'; +import { EuiText, EuiCode } from '@elastic/eui'; +import type { DataView } from '@kbn/data-views-plugin/common'; + +export interface NoResultsSuggestionDefaultProps { + dataView: DataView; +} + +export const NoResultsSuggestionDefault: React.FC = ({ + dataView, +}) => { + const dataViewName = dataView?.getName(); + const dataViewPattern = dataView?.getIndexPattern(); -export function NoResultsSuggestionDefault() { return ( - + {dataViewName && dataViewPattern ? ( + {dataViewName}, + dataViewPattern: {dataViewPattern}, + }} + /> + ) : ( + + )} ); -} +}; diff --git a/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestions.tsx b/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestions.tsx index e9cd75e022db3..9fd939cc6acfb 100644 --- a/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestions.tsx +++ b/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/no_results_suggestions.tsx @@ -111,7 +111,7 @@ export const NoResultsSuggestions: React.FC = ({ ) : ( - + ); return ( diff --git a/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/use_fetch_occurances_range.ts b/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/use_fetch_occurances_range.ts index 8ae801fc93039..e58aee4cb5cfa 100644 --- a/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/use_fetch_occurances_range.ts +++ b/src/plugins/discover/public/application/main/components/no_results/no_results_suggestions/use_fetch_occurances_range.ts @@ -46,28 +46,27 @@ export const useFetchOccurrencesRange = (params: Params): Result => { const fetchOccurrences = useCallback( async (dataView?: DataView, query?: Query | AggregateQuery, filters?: Filter[]) => { let occurrencesRange = null; - if (!dataView?.timeFieldName || !query || !mountedRef.current) { - return null; - } - abortControllerRef.current?.abort(); - abortControllerRef.current = new AbortController(); - - try { - const dslQuery = buildEsQuery( - dataView, - query ?? [], - filters ?? [], - getEsQueryConfig(uiSettings) - ); - occurrencesRange = await fetchDocumentsTimeRange({ - data, - dataView, - dslQuery, - abortSignal: abortControllerRef.current?.signal, - }); - } catch (error) { - // + if (dataView?.isTimeBased() && query && mountedRef.current) { + abortControllerRef.current?.abort(); + abortControllerRef.current = new AbortController(); + + try { + const dslQuery = buildEsQuery( + dataView, + query ?? [], + filters ?? [], + getEsQueryConfig(uiSettings) + ); + occurrencesRange = await fetchDocumentsTimeRange({ + data, + dataView, + dslQuery, + abortSignal: abortControllerRef.current?.signal, + }); + } catch (error) { + // + } } if (mountedRef.current) { @@ -115,7 +114,7 @@ async function fetchDocumentsTimeRange({ data.search.search( { params: { - index: dataView.title, + index: dataView.getIndexPattern(), size: 0, body: { query: dslQuery ?? { match_all: {} }, 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 242f2ab95a5cf..54e90c01b24f3 100644 --- a/src/plugins/discover/public/application/main/discover_main_route.tsx +++ b/src/plugins/discover/public/application/main/discover_main_route.tsx @@ -102,7 +102,12 @@ export function DiscoverMainRoute(props: Props) { return; } - const defaultDataView = await data.dataViews.getDefaultDataView(); + let defaultDataView: DataView | null = null; + try { + defaultDataView = await data.dataViews.getDefaultDataView({ displayErrors: false }); + } catch (e) { + // + } if (!defaultDataView) { setShowNoDataPage(true); diff --git a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts index 0ceb3c984a165..c53e0ec9da617 100644 --- a/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts +++ b/src/plugins/discover/public/application/main/hooks/utils/change_data_view.ts @@ -37,7 +37,14 @@ export async function changeDataView( const { dataViews, uiSettings } = services; const dataView = discoverState.internalState.getState().dataView; const state = discoverState.appState.getState(); - const nextDataView = await dataViews.get(id); + let nextDataView: DataView | null = null; + + try { + nextDataView = await dataViews.get(id, false); + } catch (e) { + // + } + if (nextDataView && dataView) { const nextAppState = getDataViewAppState( dataView, 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 fb9e182ab8224..2584d9b7c8279 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 @@ -64,10 +64,10 @@ export async function loadDataView( fetchId = dataViewSpec.id!; } - let fetchedDataView: DataView | undefined; + let fetchedDataView: DataView | null = null; // try to fetch adhoc data view first try { - fetchedDataView = fetchId ? await dataViews.get(fetchId) : undefined; + fetchedDataView = fetchId ? await dataViews.get(fetchId, false) : null; if (fetchedDataView && !fetchedDataView.isPersisted()) { return { list: dataViewList || [], @@ -82,13 +82,20 @@ export async function loadDataView( // eslint-disable-next-line no-empty } catch (e) {} + let defaultDataView: DataView | null = null; + if (!fetchedDataView) { + try { + defaultDataView = await dataViews.getDefaultDataView({ displayErrors: false }); + } catch (e) { + // + } + } + // fetch persisted data view return { list: dataViewList || [], - loaded: fetchedDataView - ? fetchedDataView - : // we can be certain that the data view exists due to an earlier hasData check - ((await dataViews.getDefaultDataView()) as DataView), + // we can be certain that the data view exists due to an earlier hasData check + loaded: fetchedDataView || defaultDataView!, stateVal: fetchId, stateValFound: !!fetchId && !!fetchedDataView, }; diff --git a/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts b/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts index 6b523d155393c..2033c222764a4 100644 --- a/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts +++ b/src/plugins/unified_field_list/public/hooks/use_existing_fields.ts @@ -106,7 +106,13 @@ export const useExistingFieldsFetcher = ( } const numberOfFetches = (currentInfo?.numberOfFetches ?? 0) + 1; - const dataView = await dataViews.get(dataViewId); + let dataView: DataView | null = null; + + try { + dataView = await dataViews.get(dataViewId, false); + } catch (e) { + // + } if (!dataView?.title) { return; @@ -155,8 +161,6 @@ export const useExistingFieldsFetcher = ( info.existingFieldsByFieldNameMap = booleanMap(existingFieldNames); info.fetchStatus = ExistenceFetchStatus.succeeded; } catch (error) { - // eslint-disable-next-line no-console - console.error(error); info.fetchStatus = ExistenceFetchStatus.failed; } } diff --git a/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts b/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts index 1209ed64f1eb5..45432fb9bba81 100644 --- a/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts +++ b/src/plugins/unified_field_list/public/hooks/use_grouped_fields.ts @@ -88,7 +88,15 @@ export function useGroupedFields({ useEffect(() => { const getDataView = async () => { if (dataViewId) { - setDataView(await services.dataViews.get(dataViewId)); + let nextDataView: DataView | null = null; + try { + nextDataView = await services.dataViews.get(dataViewId, false); + } catch (e) { + // + } + setDataView(nextDataView || null); + } else { + setDataView(null); } }; getDataView(); 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 a7f473f95b374..e828e4d1a2bc1 100644 --- a/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx +++ b/src/plugins/unified_search/public/dataview_picker/change_dataview.tsx @@ -303,8 +303,12 @@ export function ChangeDataView({ isTextBasedLangSelected={isTextBasedLangSelected} setPopoverIsOpen={setPopoverIsOpen} onChangeDataView={async (newId) => { - // refreshing the field list - await dataViews.get(newId, undefined, true); + try { + // refreshing the field list + await dataViews.get(newId, false, true); + } catch (e) { + // + } setSelectedDataViewId(newId); setPopoverIsOpen(false); if (isTextBasedLangSelected && !isTextLangTransitionModalDismissed) { @@ -355,6 +359,7 @@ export function ChangeDataView({ , { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 02f08c61ce069..8182c753868a9 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2308,7 +2308,6 @@ "discover.localMenu.shareTitle": "Partager", "discover.noMatchRoute.bannerTitleText": "Page introuvable", "discover.noResults.noDocumentsOrCheckPermissionsDescription": "Assurez-vous de disposer de l'autorisation d'afficher les index et vérifiez qu'ils contiennent des documents.", - "discover.noResults.searchExamples.noResultsBecauseOfError": "Une erreur s’est produite lors de la récupération des résultats de recherche.", "discover.noResults.searchExamples.noResultsMatchSearchCriteriaTitle": "Aucun résultat ne correspond à vos critères de recherche.", "discover.noResultsFound": "Résultat introuvable", "discover.notifications.invalidTimeRangeText": "La plage temporelle spécifiée n'est pas valide (de : \"{from}\" à \"{to}\").", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index cb19db1d673ec..ece6fbb1d5c31 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2306,7 +2306,6 @@ "discover.localMenu.shareTitle": "共有", "discover.noMatchRoute.bannerTitleText": "ページが見つかりません", "discover.noResults.noDocumentsOrCheckPermissionsDescription": "インデックスと含まれるドキュメントを表示する権限がありません。", - "discover.noResults.searchExamples.noResultsBecauseOfError": "検索結果の取得中にエラーが発生しました", "discover.noResults.searchExamples.noResultsMatchSearchCriteriaTitle": "検索条件と一致する結果がありません。", "discover.noResultsFound": "結果が見つかりませんでした", "discover.notifications.invalidTimeRangeText": "指定された時間範囲が無効です。(開始:'{from}'、終了:'{to}')", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d6ab67bb9095b..a8acae9de7337 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2310,7 +2310,6 @@ "discover.localMenu.shareTitle": "共享", "discover.noMatchRoute.bannerTitleText": "未找到页面", "discover.noResults.noDocumentsOrCheckPermissionsDescription": "确保您有权查看索引并且它们包含文档。", - "discover.noResults.searchExamples.noResultsBecauseOfError": "检索搜索结果时遇到问题", "discover.noResults.searchExamples.noResultsMatchSearchCriteriaTitle": "没有任何结果匹配您的搜索条件", "discover.noResultsFound": "找不到结果", "discover.notifications.invalidTimeRangeText": "提供的时间范围无效。(自:“{from}”,至:“{to}”)", From ec4ebd958e849b7a0e2d4bcee7e07334bf6afc50 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Tue, 14 Feb 2023 13:20:56 +0100 Subject: [PATCH 164/203] [Security Solutions] Fix update Entity Analytics Upgrade dialog text (#151104) issue: https://github.com/elastic/kibana/issues/148589 ## Summary Update `devices`=> `hosts` ### Before Change Screenshot 2023-02-14 at 10 56 06 ### After Change Screenshot 2023-02-14 at 10 54 23 ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) --- .../security_solution/public/overview/pages/translations.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/overview/pages/translations.ts b/x-pack/plugins/security_solution/public/overview/pages/translations.ts index 474bb1db94fdf..5f44e18b53cd5 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/translations.ts +++ b/x-pack/plugins/security_solution/public/overview/pages/translations.ts @@ -107,8 +107,7 @@ export const DETECTION_RESPONSE_TITLE = i18n.translate( export const ENTITY_ANALYTICS_LICENSE_DESC = i18n.translate( 'xpack.securitySolution.entityAnalytics.pageDesc', { - defaultMessage: - 'Detect threats from users and devices within your network with Entity Analytics', + defaultMessage: 'Detect threats from users and hosts within your network with Entity Analytics', } ); From 4054d2744e2cd99094d1408f4125813098d8bb2f Mon Sep 17 00:00:00 2001 From: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com> Date: Tue, 14 Feb 2023 07:25:58 -0500 Subject: [PATCH 165/203] [Cases] Adding refreshes to fix failed test (#151068) Fixes: https://github.com/elastic/kibana/issues/150962 This PR adds some index refreshes to fix tests that were running into index conflicts. Flaky test run: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1907 --- .../security_and_spaces/tests/trial/cases/push_case.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts index d6d0919be8b4a..a9d4382fc08bc 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/push_case.ts @@ -616,8 +616,7 @@ export default ({ getService }: FtrProviderContext): void => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/150962 - describe.skip('alerts', () => { + describe('alerts', () => { const defaultSignalsIndex = '.siem-signals-default-000001'; const signalID = '4679431ee0ba3209b6fcd60a255a696886fe0a7d18f5375de510ff5b68fa6b78'; const signalID2 = '1023bcfea939643c5e51fd8df53797e0ea693cee547db579ab56d96402365c1e'; @@ -656,6 +655,8 @@ export default ({ getService }: FtrProviderContext): void => { }, }); + await es.indices.refresh({ index: defaultSignalsIndex }); + await createComment({ supertest, caseId: postedCase.id, @@ -668,6 +669,8 @@ export default ({ getService }: FtrProviderContext): void => { }, }); + await es.indices.refresh({ index: defaultSignalsIndex }); + await pushCase({ supertest, caseId: postedCase.id, From 38f186fdf858291452e31495d4caac1534963bbb Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 14 Feb 2023 13:27:17 +0100 Subject: [PATCH 166/203] [Synthetics] Skip flaky test (#151118) --- x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts index bf4ecd526e911..b3dcd9aaa4421 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/index.ts @@ -17,7 +17,7 @@ export * from './private_locations.journey'; export * from './alerting_default.journey'; export * from './global_parameters.journey'; export * from './detail_flyout'; -export * from './alert_rules/default_status_alert.journey'; +// export * from './alert_rules/default_status_alert.journey'; export * from './test_now_mode.journey'; export * from './data_retention.journey'; export * from './monitor_details_page/monitor_summary.journey'; From cf94e1a288e07212dbf3403e7c01deec15c0ef6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loix?= Date: Tue, 14 Feb 2023 12:30:42 +0000 Subject: [PATCH 167/203] [Content management] Add base core services (#150692) --- .../public/registry/content_type.test.ts | 16 +- .../public/registry/content_type.ts | 12 +- .../public/registry/registry.test.ts | 8 +- .../public/registry/registry.ts | 2 +- .../server/core/content_type.ts | 39 ++ .../server/core/core.test.ts | 616 ++++++++++++++++++ .../content_management/server/core/core.ts | 56 ++ .../content_management/server/core/crud.ts | 241 +++++++ .../server/core/event_bus.ts | 136 ++++ .../server/core/event_types.ts | 139 ++++ .../content_management/server/core/index.ts | 17 + .../server/core/mocks/in_memory_storage.ts | 141 ++++ .../server/core/mocks/index.ts | 10 + .../server/core/registry.ts | 56 ++ .../content_management/server/core/types.ts | 38 ++ .../content_management/server/plugin.ts | 23 +- src/plugins/content_management/tsconfig.json | 1 + 17 files changed, 1529 insertions(+), 22 deletions(-) create mode 100644 src/plugins/content_management/server/core/content_type.ts create mode 100644 src/plugins/content_management/server/core/core.test.ts create mode 100644 src/plugins/content_management/server/core/core.ts create mode 100644 src/plugins/content_management/server/core/crud.ts create mode 100644 src/plugins/content_management/server/core/event_bus.ts create mode 100644 src/plugins/content_management/server/core/event_types.ts create mode 100644 src/plugins/content_management/server/core/index.ts create mode 100644 src/plugins/content_management/server/core/mocks/in_memory_storage.ts create mode 100644 src/plugins/content_management/server/core/mocks/index.ts create mode 100644 src/plugins/content_management/server/core/registry.ts create mode 100644 src/plugins/content_management/server/core/types.ts diff --git a/src/plugins/content_management/public/registry/content_type.test.ts b/src/plugins/content_management/public/registry/content_type.test.ts index c6a5e18fd6f6c..dd06ea658676e 100644 --- a/src/plugins/content_management/public/registry/content_type.test.ts +++ b/src/plugins/content_management/public/registry/content_type.test.ts @@ -12,10 +12,10 @@ import type { ContentTypeDefinition } from './content_type_definition'; test('create a content type with just an id', () => { const type = new ContentType({ id: 'test' }); - expect(type.id()).toBe('test'); - expect(type.name()).toBe('test'); - expect(type.icon()).toBe('questionInCircle'); - expect(type.description()).toBe(''); + expect(type.id).toBe('test'); + expect(type.name).toBe('test'); + expect(type.icon).toBe('questionInCircle'); + expect(type.description).toBe(''); }); test('create a content type with all the full definition', () => { @@ -27,9 +27,9 @@ test('create a content type with all the full definition', () => { }; const type = new ContentType(definition); - expect(type.id()).toBe(definition.id); - expect(type.name()).toBe(definition.name); - expect(type.icon()).toBe(definition.icon); - expect(type.description()).toBe(definition.description); + expect(type.id).toBe(definition.id); + expect(type.name).toBe(definition.name); + expect(type.icon).toBe(definition.icon); + expect(type.description).toBe(definition.description); expect(type.definition).toEqual(definition); }); diff --git a/src/plugins/content_management/public/registry/content_type.ts b/src/plugins/content_management/public/registry/content_type.ts index 213a1c5427e0e..fa55b890689fe 100644 --- a/src/plugins/content_management/public/registry/content_type.ts +++ b/src/plugins/content_management/public/registry/content_type.ts @@ -12,23 +12,23 @@ import type { CrudClient } from '../crud_client'; export class ContentType { constructor(public readonly definition: ContentTypeDefinition) {} - id(): string { + public get id(): string { return this.definition.id; } - name(): string { - return this.definition.name ?? this.id(); + public get name(): string { + return this.definition.name ?? this.id; } - description(): string { + public get description(): string { return this.definition.description ?? ''; } - icon(): string { + public get icon(): string { return this.definition.icon ?? 'questionInCircle'; } - crud(): CrudClient | undefined { + public get crud(): CrudClient | undefined { return this.definition.crud; } } diff --git a/src/plugins/content_management/public/registry/registry.test.ts b/src/plugins/content_management/public/registry/registry.test.ts index f6284ddd31f64..20c20c161badd 100644 --- a/src/plugins/content_management/public/registry/registry.test.ts +++ b/src/plugins/content_management/public/registry/registry.test.ts @@ -22,10 +22,10 @@ test('registering a content type', () => { description: 'Test description', }); - expect(type.id()).toBe('test'); - expect(type.name()).toBe('Test'); - expect(type.icon()).toBe('test'); - expect(type.description()).toBe('Test description'); + expect(type.id).toBe('test'); + expect(type.name).toBe('Test'); + expect(type.icon).toBe('test'); + expect(type.description).toBe('Test description'); }); test('registering already registered content type throws', () => { diff --git a/src/plugins/content_management/public/registry/registry.ts b/src/plugins/content_management/public/registry/registry.ts index 6648888122bc0..7c96a0d79b251 100644 --- a/src/plugins/content_management/public/registry/registry.ts +++ b/src/plugins/content_management/public/registry/registry.ts @@ -17,7 +17,7 @@ export class ContentTypeRegistry { throw new Error(`Content type with id "${definition.id}" already registered.`); } const type = new ContentType(definition); - this.types.set(type.id(), type); + this.types.set(type.id, type); return type; } diff --git a/src/plugins/content_management/server/core/content_type.ts b/src/plugins/content_management/server/core/content_type.ts new file mode 100644 index 0000000000000..5853cd3e77556 --- /dev/null +++ b/src/plugins/content_management/server/core/content_type.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 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 { ContentCrud } from './crud'; +import { EventBus } from './event_bus'; +import { ContentStorage, ContentTypeDefinition } from './types'; + +export class ContentType { + /** Content definition. */ + private readonly _definition: ContentTypeDefinition; + /** Content crud instance. */ + private readonly contentCrud: ContentCrud; + + constructor(definition: ContentTypeDefinition, eventBus: EventBus) { + this._definition = definition; + this.contentCrud = new ContentCrud(definition.id, definition.storage, { eventBus }); + } + + public get id() { + return this._definition.id; + } + + public get definition() { + return this._definition; + } + + public get storage() { + return this._definition.storage; + } + + public get crud() { + return this.contentCrud; + } +} diff --git a/src/plugins/content_management/server/core/core.test.ts b/src/plugins/content_management/server/core/core.test.ts new file mode 100644 index 0000000000000..19670740290f8 --- /dev/null +++ b/src/plugins/content_management/server/core/core.test.ts @@ -0,0 +1,616 @@ +/* + * Copyright 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 { loggingSystemMock } from '@kbn/core/server/mocks'; +import { Core } from './core'; +import { createMemoryStorage, MockContent } from './mocks'; +import { ContentRegistry } from './registry'; +import { ContentCrud } from './crud'; +import type { + GetItemStart, + GetItemSuccess, + GetItemError, + CreateItemStart, + CreateItemSuccess, + CreateItemError, + UpdateItemStart, + UpdateItemSuccess, + UpdateItemError, + DeleteItemStart, + DeleteItemSuccess, + DeleteItemError, +} from './event_types'; + +const logger = loggingSystemMock.createLogger(); + +const FOO_CONTENT_ID = 'foo'; + +const setup = ({ registerFooType = false }: { registerFooType?: boolean } = {}) => { + const ctx = {}; + + const core = new Core({ logger }); + const coreSetup = core.setup(); + const contentDefinition = { + id: FOO_CONTENT_ID, + storage: createMemoryStorage(), + }; + const cleanUp = () => { + coreSetup.api.eventBus.stop(); + }; + + let fooContentCrud: ContentCrud | undefined; + + if (registerFooType) { + coreSetup.api.register(contentDefinition); + fooContentCrud = coreSetup.api.crud(FOO_CONTENT_ID); + } + + return { + core, + coreSetup, + contentDefinition, + ctx, + fooContentCrud, + cleanUp, + eventBus: coreSetup.api.eventBus, + }; +}; + +describe('Content Core', () => { + describe('setup()', () => { + test('should return the registry and the public api', () => { + const { coreSetup, cleanUp } = setup(); + + expect(coreSetup.contentRegistry).toBeInstanceOf(ContentRegistry); + expect(Object.keys(coreSetup.api).sort()).toEqual(['crud', 'eventBus', 'register']); + + cleanUp(); + }); + + describe('api', () => { + describe('register()', () => { + test('should expose the register handler from the registry instance', () => { + const { coreSetup, cleanUp, contentDefinition } = setup(); + + const { + contentRegistry, + api: { register }, + } = coreSetup; + + expect(contentRegistry.isContentRegistered(FOO_CONTENT_ID)).toBe(false); + + register(contentDefinition); + + // Make sure the "register" exposed by the api is indeed registring + // the content into our "contentRegistry" instance + expect(contentRegistry.isContentRegistered(FOO_CONTENT_ID)).toBe(true); + expect(contentRegistry.getDefinition(FOO_CONTENT_ID)).toBe(contentDefinition); + + cleanUp(); + }); + }); + + describe('crud()', () => { + test('get()', async () => { + const { fooContentCrud, ctx, cleanUp } = setup({ registerFooType: true }); + + const res = await fooContentCrud!.get(ctx, '1'); + expect(res.item).toBeUndefined(); + + cleanUp(); + }); + + test('get() - options are forwared to storage layer', async () => { + const { fooContentCrud, ctx, cleanUp } = setup({ registerFooType: true }); + + const res = await fooContentCrud!.get(ctx, '1', { forwardInResponse: { foo: 'bar' } }); + expect(res).toEqual({ + contentTypeId: FOO_CONTENT_ID, + item: { + // Options forwared in response + options: { foo: 'bar' }, + }, + }); + + cleanUp(); + }); + + test('create()', async () => { + const { fooContentCrud, ctx, cleanUp } = setup({ registerFooType: true }); + + const res = await fooContentCrud!.get(ctx, '1234'); + expect(res.item).toBeUndefined(); + await fooContentCrud!.create, { id: string }>( + ctx, + { title: 'Hello' }, + { id: '1234' } // We send this "id" option to specify the id of the content created + ); + expect(fooContentCrud!.get(ctx, '1234')).resolves.toEqual({ + contentTypeId: FOO_CONTENT_ID, + item: { + id: '1234', + title: 'Hello', + }, + }); + + cleanUp(); + }); + + test('update()', async () => { + const { fooContentCrud, ctx, cleanUp } = setup({ registerFooType: true }); + + await fooContentCrud!.create, { id: string }>( + ctx, + { title: 'Hello' }, + { id: '1234' } + ); + await fooContentCrud!.update>(ctx, '1234', { title: 'changed' }); + expect(fooContentCrud!.get(ctx, '1234')).resolves.toEqual({ + contentTypeId: FOO_CONTENT_ID, + item: { + id: '1234', + title: 'changed', + }, + }); + + cleanUp(); + }); + + test('update() - options are forwared to storage layer', async () => { + const { fooContentCrud, ctx, cleanUp } = setup({ registerFooType: true }); + + await fooContentCrud!.create, { id: string }>( + ctx, + { title: 'Hello' }, + { id: '1234' } + ); + const res = await fooContentCrud!.update>( + ctx, + '1234', + { title: 'changed' }, + { forwardInResponse: { foo: 'bar' } } + ); + + expect(res).toEqual({ + contentTypeId: FOO_CONTENT_ID, + result: { + id: '1234', + title: 'changed', + // Options forwared in response + options: { foo: 'bar' }, + }, + }); + + expect(fooContentCrud!.get(ctx, '1234')).resolves.toEqual({ + contentTypeId: FOO_CONTENT_ID, + item: { + id: '1234', + title: 'changed', + }, + }); + + cleanUp(); + }); + + test('delete()', async () => { + const { fooContentCrud, ctx, cleanUp } = setup({ registerFooType: true }); + + await fooContentCrud!.create, { id: string }>( + ctx, + { title: 'Hello' }, + { id: '1234' } + ); + expect(fooContentCrud!.get(ctx, '1234')).resolves.toEqual({ + contentTypeId: FOO_CONTENT_ID, + item: expect.any(Object), + }); + await fooContentCrud!.delete(ctx, '1234'); + expect(fooContentCrud!.get(ctx, '1234')).resolves.toEqual({ + contentTypeId: FOO_CONTENT_ID, + item: undefined, + }); + + cleanUp(); + }); + + test('delete() - options are forwared to storage layer', async () => { + const { fooContentCrud, ctx, cleanUp } = setup({ registerFooType: true }); + + await fooContentCrud!.create, { id: string }>( + ctx, + { title: 'Hello' }, + { id: '1234' } + ); + const res = await fooContentCrud!.delete(ctx, '1234', { + forwardInResponse: { foo: 'bar' }, + }); + expect(res).toMatchObject({ result: { options: { foo: 'bar' } } }); + + cleanUp(); + }); + }); + + describe('eventBus', () => { + test('should allow to emit and subscribe to events', () => { + const { coreSetup, cleanUp } = setup(); + + const { + api: { eventBus }, + } = coreSetup; + + const listener = jest.fn(); + const subscription = eventBus.events$.subscribe(listener); + + const event: GetItemStart = { + type: 'getItemStart', + contentId: '123', + contentTypeId: FOO_CONTENT_ID, + }; + eventBus.emit(event); + + expect(listener).toHaveBeenCalledWith(event); + subscription.unsubscribe(); + + cleanUp(); + }); + + test('should allow to subscribe to a single event', () => { + const { coreSetup, cleanUp } = setup(); + + const { + api: { eventBus }, + } = coreSetup; + + const listener = jest.fn(); + // Listen to all "getItemStart" events, regardless of the content type + const unsubscribe = eventBus.on('getItemStart', listener); + + const event: GetItemStart = { + type: 'getItemStart', + contentId: '123', + contentTypeId: FOO_CONTENT_ID, + }; + eventBus.emit(event); + + expect(listener).toHaveBeenCalledWith(event); + + // Test the returned unsubscribe() handler + listener.mockReset(); + unsubscribe(); + + eventBus.emit(event); + expect(listener).not.toHaveBeenCalledWith(event); + + cleanUp(); + }); + + test('should validate that the content type is registered when subscribing to single event with content type', () => { + const { coreSetup, cleanUp } = setup(); + + const { + api: { eventBus }, + } = coreSetup; + + expect(() => { + eventBus.on('getItemStart', FOO_CONTENT_ID, jest.fn()); + }).toThrow('Invalid content type [foo].'); + + cleanUp(); + }); + + test('should allow to subscribe to a single event for a single content type', async () => { + const { coreSetup, ctx, contentDefinition, cleanUp } = setup(); + + const { + api: { eventBus, register, crud }, + } = coreSetup; + + register(contentDefinition); + + await crud(FOO_CONTENT_ID).create, { id: string }>( + ctx, + { title: 'Hello' }, + { id: '1234' } + ); + + const listener = jest.fn(); + + // Listen to "getItemStart" events *only* on the "foo" content type + eventBus.on('getItemStart', FOO_CONTENT_ID, listener); + + let event: GetItemStart = { + type: 'getItemStart', + contentId: '123', + contentTypeId: 'other', // other type should not call listener + }; + eventBus.emit(event); + + expect(listener).not.toHaveBeenCalledWith(event); + + event = { + type: 'getItemStart', + contentId: '123', + contentTypeId: FOO_CONTENT_ID, + }; + eventBus.emit(event); + + expect(listener).toHaveBeenCalledWith(event); + + cleanUp(); + }); + + describe('crud operations should emit start|success|error events', () => { + test('get()', async () => { + const { fooContentCrud, eventBus, ctx, cleanUp } = setup({ + registerFooType: true, + }); + + const data = { title: 'Hello' }; + + await fooContentCrud!.create, { id: string }>(ctx, data, { + id: '1234', + }); + + const listener = jest.fn(); + const sub = eventBus.events$.subscribe(listener); + + const promise = fooContentCrud!.get(ctx, '1234', { someOption: 'baz' }); + + const getItemStart: GetItemStart = { + type: 'getItemStart', + contentId: '1234', + contentTypeId: FOO_CONTENT_ID, + options: { someOption: 'baz' }, + }; + + expect(listener).toHaveBeenCalledWith(getItemStart); + + await promise; + + const getItemSuccess: GetItemSuccess = { + type: 'getItemSuccess', + contentId: '1234', + data: { + id: '1234', + ...data, + }, + contentTypeId: FOO_CONTENT_ID, + }; + + expect(listener).toHaveBeenCalledWith(getItemSuccess); + + listener.mockReset(); + + const errorMessage = 'Ohhh no!'; + const reject = jest.fn(); + await fooContentCrud!.get(ctx, '1234', { errorToThrow: errorMessage }).catch(reject); + + const getItemError: GetItemError = { + type: 'getItemError', + contentId: '1234', + contentTypeId: FOO_CONTENT_ID, + error: errorMessage, + options: { errorToThrow: errorMessage }, + }; + + expect(listener).toHaveBeenLastCalledWith(getItemError); + + expect(reject).toHaveBeenCalledWith(new Error(errorMessage)); + + sub.unsubscribe(); + + cleanUp(); + }); + + test('create()', async () => { + const { fooContentCrud, ctx, eventBus, cleanUp } = setup({ + registerFooType: true, + }); + + const data = { title: 'Hello' }; + + const listener = jest.fn(); + const sub = eventBus.events$.subscribe(listener); + + const promise = fooContentCrud!.create, { id: string }>( + ctx, + data, + { + id: '1234', + } + ); + + const createItemStart: CreateItemStart = { + type: 'createItemStart', + contentTypeId: FOO_CONTENT_ID, + data, + options: { id: '1234' }, + }; + + expect(listener).toHaveBeenCalledWith(createItemStart); + + await promise; + + const createItemSuccess: CreateItemSuccess = { + type: 'createItemSuccess', + data: { + id: '1234', + ...data, + }, + contentTypeId: FOO_CONTENT_ID, + options: { id: '1234' }, + }; + + expect(listener).toHaveBeenCalledWith(createItemSuccess); + + listener.mockReset(); + + const errorMessage = 'Ohhh no!'; + const reject = jest.fn(); + await fooContentCrud! + .create, { id: string; errorToThrow: string }>(ctx, data, { + id: '1234', + errorToThrow: errorMessage, + }) + .catch(reject); + + const createItemError: CreateItemError = { + type: 'createItemError', + contentTypeId: FOO_CONTENT_ID, + data, + error: errorMessage, + options: { id: '1234', errorToThrow: errorMessage }, + }; + + expect(listener).toHaveBeenLastCalledWith(createItemError); + + expect(reject).toHaveBeenCalledWith(new Error(errorMessage)); + + sub.unsubscribe(); + cleanUp(); + }); + + test('update()', async () => { + const { fooContentCrud, ctx, eventBus, cleanUp } = setup({ + registerFooType: true, + }); + + await fooContentCrud!.create, { id: string }>( + ctx, + { title: 'Hello' }, + { + id: '1234', + } + ); + + const listener = jest.fn(); + const sub = eventBus.events$.subscribe(listener); + + const data = { title: 'Updated' }; + + const promise = await fooContentCrud!.update(ctx, '1234', data, { someOptions: 'baz' }); + + const updateItemStart: UpdateItemStart = { + type: 'updateItemStart', + contentId: '1234', + contentTypeId: FOO_CONTENT_ID, + data, + options: { someOptions: 'baz' }, + }; + + expect(listener).toHaveBeenCalledWith(updateItemStart); + + await promise; + + const updateItemSuccess: UpdateItemSuccess = { + type: 'updateItemSuccess', + contentId: '1234', + contentTypeId: FOO_CONTENT_ID, + data: { + id: '1234', + ...data, + }, + options: { someOptions: 'baz' }, + }; + + expect(listener).toHaveBeenCalledWith(updateItemSuccess); + + listener.mockReset(); + + const errorMessage = 'Ohhh no!'; + const reject = jest.fn(); + await fooContentCrud! + .update(ctx, '1234', data, { + errorToThrow: errorMessage, + }) + .catch(reject); + + const updateItemError: UpdateItemError = { + type: 'updateItemError', + contentTypeId: FOO_CONTENT_ID, + contentId: '1234', + data, + error: errorMessage, + options: { errorToThrow: errorMessage }, + }; + + expect(listener).toHaveBeenLastCalledWith(updateItemError); + + expect(reject).toHaveBeenCalledWith(new Error(errorMessage)); + + sub.unsubscribe(); + cleanUp(); + }); + + test('delete()', async () => { + const { fooContentCrud, ctx, eventBus, cleanUp } = setup({ + registerFooType: true, + }); + + await fooContentCrud!.create, { id: string }>( + ctx, + { title: 'Hello' }, + { + id: '1234', + } + ); + + const listener = jest.fn(); + const sub = eventBus.events$.subscribe(listener); + + const promise = await fooContentCrud!.delete(ctx, '1234', { someOptions: 'baz' }); + + const deleteItemStart: DeleteItemStart = { + type: 'deleteItemStart', + contentId: '1234', + contentTypeId: FOO_CONTENT_ID, + options: { someOptions: 'baz' }, + }; + + expect(listener).toHaveBeenCalledWith(deleteItemStart); + + await promise; + + const deleteItemSuccess: DeleteItemSuccess = { + type: 'deleteItemSuccess', + contentId: '1234', + contentTypeId: FOO_CONTENT_ID, + options: { someOptions: 'baz' }, + }; + + expect(listener).toHaveBeenCalledWith(deleteItemSuccess); + + listener.mockReset(); + + const errorMessage = 'Ohhh no!'; + const reject = jest.fn(); + await fooContentCrud! + .delete(ctx, '1234', { + errorToThrow: errorMessage, + }) + .catch(reject); + + const deleteItemError: DeleteItemError = { + type: 'deleteItemError', + contentTypeId: FOO_CONTENT_ID, + contentId: '1234', + error: errorMessage, + options: { errorToThrow: errorMessage }, + }; + + expect(listener).toHaveBeenLastCalledWith(deleteItemError); + + expect(reject).toHaveBeenCalledWith(new Error(errorMessage)); + + sub.unsubscribe(); + cleanUp(); + }); + }); + }); + }); + }); +}); diff --git a/src/plugins/content_management/server/core/core.ts b/src/plugins/content_management/server/core/core.ts new file mode 100644 index 0000000000000..2efc6546fa64e --- /dev/null +++ b/src/plugins/content_management/server/core/core.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { Logger } from '@kbn/core/server'; + +import { ContentCrud } from './crud'; +import { EventBus } from './event_bus'; +import { ContentRegistry } from './registry'; + +export interface CoreApi { + /** + * Register a new content in the registry. + * + * @param contentType The content type to register + * @param config The content configuration + */ + register: ContentRegistry['register']; + /** Handler to retrieve a content crud instance */ + crud: (contentType: string) => ContentCrud; + /** Content management event bus */ + eventBus: EventBus; +} + +export interface CoreSetup { + /** Content registry instance */ + contentRegistry: ContentRegistry; + /** Api exposed to other plugins */ + api: CoreApi; +} + +export class Core { + private contentRegistry: ContentRegistry; + private eventBus: EventBus; + + constructor({ logger }: { logger: Logger }) { + const contentTypeValidator = (contentType: string) => + this.contentRegistry?.isContentRegistered(contentType) ?? false; + this.eventBus = new EventBus(contentTypeValidator); + this.contentRegistry = new ContentRegistry(this.eventBus); + } + + setup(): CoreSetup { + return { + contentRegistry: this.contentRegistry, + api: { + register: this.contentRegistry.register.bind(this.contentRegistry), + crud: this.contentRegistry.getCrud.bind(this.contentRegistry), + eventBus: this.eventBus, + }, + }; + } +} diff --git a/src/plugins/content_management/server/core/crud.ts b/src/plugins/content_management/server/core/crud.ts new file mode 100644 index 0000000000000..e56d79e8f47b2 --- /dev/null +++ b/src/plugins/content_management/server/core/crud.ts @@ -0,0 +1,241 @@ +/* + * Copyright 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 { EventBus } from './event_bus'; +import type { ContentStorage, StorageContext } from './types'; + +export interface GetResponse { + contentTypeId: string; + item?: T; +} + +export interface BulkGetResponse { + contentTypeId: string; + items: T; +} + +export interface CreateItemResponse { + contentTypeId: string; + result: T; +} + +export interface UpdateItemResponse { + contentTypeId: string; + result: T; +} + +export interface DeleteItemResponse { + contentTypeId: string; + result: T; +} + +export class ContentCrud implements ContentStorage { + private storage: ContentStorage; + private eventBus: EventBus; + public contentTypeId: string; + + constructor( + contentTypeId: string, + contentStorage: ContentStorage, + { + eventBus, + }: { + eventBus: EventBus; + } + ) { + this.contentTypeId = contentTypeId; + this.storage = contentStorage; + this.eventBus = eventBus; + } + + public async get( + ctx: StorageContext, + contentId: string, + options?: Options + ): Promise> { + this.eventBus.emit({ + type: 'getItemStart', + contentId, + contentTypeId: this.contentTypeId, + options, + }); + + try { + const item = await this.storage.get(ctx, contentId, options); + + this.eventBus.emit({ + type: 'getItemSuccess', + contentId, + contentTypeId: this.contentTypeId, + data: item, + }); + + return { contentTypeId: this.contentTypeId, item }; + } catch (e) { + this.eventBus.emit({ + type: 'getItemError', + contentId, + contentTypeId: this.contentTypeId, + options, + error: e.message, + }); + + throw e; + } + } + + public async bulkGet( + ctx: StorageContext, + ids: string[], + options?: Options + ): Promise> { + this.eventBus.emit({ + type: 'bulkGetItemStart', + contentTypeId: this.contentTypeId, + ids, + options, + }); + + try { + const items = await this.storage.bulkGet(ctx, ids, options); + + this.eventBus.emit({ + type: 'bulkGetItemSuccess', + ids, + contentTypeId: this.contentTypeId, + data: items, + }); + + return { + contentTypeId: this.contentTypeId, + items, + }; + } catch (e) { + this.eventBus.emit({ + type: 'bulkGetItemError', + ids, + contentTypeId: this.contentTypeId, + options, + error: e, + }); + + throw e; + } + } + + public async create( + ctx: StorageContext, + data: Data, + options?: Options + ): Promise> { + this.eventBus.emit({ + type: 'createItemStart', + contentTypeId: this.contentTypeId, + data, + options, + }); + + try { + const result = await this.storage.create(ctx, data, options); + + this.eventBus.emit({ + type: 'createItemSuccess', + contentTypeId: this.contentTypeId, + data: result, + options, + }); + + return { contentTypeId: this.contentTypeId, result }; + } catch (e) { + this.eventBus.emit({ + type: 'createItemError', + contentTypeId: this.contentTypeId, + data, + options, + error: e.message, + }); + + throw e; + } + } + + public async update( + ctx: StorageContext, + id: string, + data: Data, + options?: Options + ): Promise> { + this.eventBus.emit({ + type: 'updateItemStart', + contentId: id, + contentTypeId: this.contentTypeId, + data, + options, + }); + + try { + const result = await this.storage.update(ctx, id, data, options); + + this.eventBus.emit({ + type: 'updateItemSuccess', + contentId: id, + contentTypeId: this.contentTypeId, + data: result, + options, + }); + + return { contentTypeId: this.contentTypeId, result }; + } catch (e) { + this.eventBus.emit({ + type: 'updateItemError', + contentId: id, + contentTypeId: this.contentTypeId, + data, + options, + error: e.message, + }); + + throw e; + } + } + + public async delete( + ctx: StorageContext, + id: string, + options?: Options + ): Promise> { + this.eventBus.emit({ + type: 'deleteItemStart', + contentId: id, + contentTypeId: this.contentTypeId, + options, + }); + + try { + const result = await this.storage.delete(ctx, id, options); + + this.eventBus.emit({ + type: 'deleteItemSuccess', + contentId: id, + contentTypeId: this.contentTypeId, + options, + }); + + return { contentTypeId: this.contentTypeId, result }; + } catch (e) { + this.eventBus.emit({ + type: 'deleteItemError', + contentId: id, + contentTypeId: this.contentTypeId, + options, + error: e.message, + }); + + throw e; + } + } +} diff --git a/src/plugins/content_management/server/core/event_bus.ts b/src/plugins/content_management/server/core/event_bus.ts new file mode 100644 index 0000000000000..88245deb5df0a --- /dev/null +++ b/src/plugins/content_management/server/core/event_bus.ts @@ -0,0 +1,136 @@ +/* + * Copyright 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 { Subject } from 'rxjs'; +import type { Subscription } from 'rxjs'; + +import type { ContentEvent, ContentEventType } from './event_types'; + +/** Key used to represent all content types */ +const ALL_TYPES_KEY = '*'; + +/** + * Content event listener + */ +export type EventListener = (arg: ContentEvent) => void; + +/** + * Event bus for all content generated events + */ +export class EventBus { + /** The events Rxjs Subject */ + private _events$: Subject; + /** Map of listener for each content type */ + private eventListeners = new Map< + ContentEventType, + { [contentType: string]: Set } + >(); + /** Subscription to the _events$ Observable */ + private eventsSubscription: Subscription; + + /** + * @param contentTypeValidator Handler to validate if a content type is valid or not + */ + constructor(private contentTypeValidator?: (contentType: string) => boolean) { + this._events$ = new Subject(); + this.eventsSubscription = this._events$.subscribe((event) => { + const eventListeners = this.eventListeners.get(event.type); + + if (eventListeners) { + const listeners = [ + ...(eventListeners[event.contentTypeId] ?? []), + ...(eventListeners[ALL_TYPES_KEY] ?? []), + ]; + listeners.forEach((cb) => { + cb(event); + }); + } + }); + } + + /** + * + * + * @param type The event type e.g. "getItemSuccess") + * @param cb Callback to execute + * + * @example + * + * ```ts + * // Register an event for all content types + * eventBus.on('getItemSuccess', (event) => {}) + * + * // Register an event for the "dashboard" content type + * * eventBus.on('getItemSuccess', 'dashboard', (event) => {}) + * ``` + */ + + /** + * Register an event listener for specific events on specific content types + * + * @param eventType The event type to listen to + * @param contentType The content type to listen to (if not specified all content types will send the event type) + * @param cb Handler to call when the event occurs + * + * @returns Handler to unsubscribe + */ + on(eventType: ContentEventType, cb: EventListener): () => void; + on( + eventType: ContentEventType, + contentType: ContentType, + cb: EventListener + ): () => void; + on( + eventType: ContentEventType, + _contentType: ContentType | EventListener, + _cb?: EventListener + ): () => void { + const contentType = typeof _contentType === 'function' ? ALL_TYPES_KEY : _contentType; + const cb = typeof _contentType === 'function' ? _contentType : _cb!; + + if (contentType !== ALL_TYPES_KEY) { + const isContentTypeValid = this.contentTypeValidator?.(contentType) ?? true; + if (!isContentTypeValid) { + throw new Error(`Invalid content type [${contentType}].`); + } + } + + if (!this.eventListeners.has(eventType)) { + this.eventListeners.set(eventType, {}); + } + + const eventTypeListeners = this.eventListeners.get(eventType)!; + + if (eventTypeListeners[contentType] === undefined) { + eventTypeListeners[contentType] = new Set(); + } + + eventTypeListeners[contentType].add(cb); + + return () => { + eventTypeListeners[contentType].delete(cb); + }; + } + + /** + * Send an event to the CM event bus + * @param event The event to send + */ + emit(event: ContentEvent) { + this._events$.next(event); + } + + /** Content management events Observable */ + public get events$() { + return this._events$.asObservable(); + } + + stop() { + this.eventsSubscription.unsubscribe(); + } +} diff --git a/src/plugins/content_management/server/core/event_types.ts b/src/plugins/content_management/server/core/event_types.ts new file mode 100644 index 0000000000000..815ea9a4f6710 --- /dev/null +++ b/src/plugins/content_management/server/core/event_types.ts @@ -0,0 +1,139 @@ +/* + * Copyright 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 interface GetItemStart { + type: 'getItemStart'; + contentId: string; + contentTypeId: string; + options?: object; +} + +export interface GetItemSuccess { + type: 'getItemSuccess'; + contentId: string; + contentTypeId: string; + data: unknown; +} + +export interface GetItemError { + type: 'getItemError'; + contentId: string; + contentTypeId: string; + error: unknown; + options?: object; +} + +export interface BulkGetItemStart { + type: 'bulkGetItemStart'; + ids: string[]; + contentTypeId: string; + options?: object; +} + +export interface BulkGetItemSuccess { + type: 'bulkGetItemSuccess'; + ids: string[]; + contentTypeId: string; + data: unknown; +} + +export interface BulkGetItemError { + type: 'bulkGetItemError'; + ids: string[]; + contentTypeId: string; + error: unknown; + options?: object; +} + +export interface CreateItemStart { + type: 'createItemStart'; + contentTypeId: string; + data: object; + options?: object; +} + +export interface CreateItemSuccess { + type: 'createItemSuccess'; + contentTypeId: string; + data: object; + options?: object; +} + +export interface CreateItemError { + type: 'createItemError'; + contentTypeId: string; + data: object; + error: unknown; + options?: object; +} + +export interface UpdateItemStart { + type: 'updateItemStart'; + contentId: string; + contentTypeId: string; + data: object; + options?: object; +} + +export interface UpdateItemSuccess { + type: 'updateItemSuccess'; + contentId: string; + contentTypeId: string; + data: object; + options?: object; +} + +export interface UpdateItemError { + type: 'updateItemError'; + contentId: string; + contentTypeId: string; + data: object; + error: unknown; + options?: object; +} + +export interface DeleteItemStart { + type: 'deleteItemStart'; + contentId: string; + contentTypeId: string; + options?: object; +} + +export interface DeleteItemSuccess { + type: 'deleteItemSuccess'; + contentId: string; + contentTypeId: string; + options?: object; +} + +export interface DeleteItemError { + type: 'deleteItemError'; + contentId: string; + contentTypeId: string; + error: unknown; + options?: object; +} + +export type ContentEvent = + | GetItemStart + | GetItemSuccess + | GetItemError + | BulkGetItemStart + | BulkGetItemSuccess + | BulkGetItemError + | CreateItemStart + | CreateItemSuccess + | CreateItemError + | UpdateItemStart + | UpdateItemSuccess + | UpdateItemError + | DeleteItemStart + | DeleteItemSuccess + | DeleteItemError; + +export type ContentEventType = ContentEvent['type']; diff --git a/src/plugins/content_management/server/core/index.ts b/src/plugins/content_management/server/core/index.ts new file mode 100644 index 0000000000000..f292f5fa2df9a --- /dev/null +++ b/src/plugins/content_management/server/core/index.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. + */ + +export { Core } from './core'; + +export type { CoreApi } from './core'; + +export type { ContentType } from './content_type'; + +export type { ContentStorage, ContentTypeDefinition, StorageContext } from './types'; + +export type { ContentRegistry } from './registry'; diff --git a/src/plugins/content_management/server/core/mocks/in_memory_storage.ts b/src/plugins/content_management/server/core/mocks/in_memory_storage.ts new file mode 100644 index 0000000000000..a2297731198af --- /dev/null +++ b/src/plugins/content_management/server/core/mocks/in_memory_storage.ts @@ -0,0 +1,141 @@ +/* + * Copyright 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 { ContentStorage, StorageContext } from '../types'; + +export interface MockContent { + id: string; + title: string; +} + +let idx = 0; + +class InMemoryStorage implements ContentStorage { + private db: Map = new Map(); + + async get( + ctx: StorageContext, + id: string, + { forwardInResponse, errorToThrow }: { forwardInResponse?: object; errorToThrow?: string } = {} + ) { + // This allows us to test that proper error events are thrown when the storage layer op fails + if (errorToThrow) { + throw new Error(errorToThrow); + } + + if (forwardInResponse) { + // We add this so we can test that options are passed down to the storage layer + return { + ...(await this.db.get(id)), + options: forwardInResponse, + }; + } + return this.db.get(id); + } + + async bulkGet( + ctx: StorageContext, + ids: string[], + { forwardInResponse }: { forwardInResponse?: object } = {} + ) { + return ids.map((id) => this.db.get(id)); + } + + async create( + ctx: StorageContext, + data: Omit, + { id: _id, errorToThrow }: { id?: string; errorToThrow?: string } = {} + ): Promise { + // This allows us to test that proper error events are thrown when the storage layer op fails + if (errorToThrow) { + throw new Error(errorToThrow); + } + + const nextId = idx++; + const id = _id ?? nextId.toString(); + + const content: MockContent = { + ...data, + id, + }; + + this.db.set(id, content); + + return content; + } + + async update( + ctx: StorageContext, + id: string, + data: Partial>, + { forwardInResponse, errorToThrow }: { forwardInResponse?: object; errorToThrow?: string } = {} + ) { + // This allows us to test that proper error events are thrown when the storage layer op fails + if (errorToThrow) { + throw new Error(errorToThrow); + } + + const content = this.db.get(id); + if (!content) { + throw new Error(`Content to update not found [${id}].`); + } + + const updatedContent = { + ...content, + ...data, + }; + + this.db.set(id, updatedContent); + + if (forwardInResponse) { + // We add this so we can test that options are passed down to the storage layer + return { + ...updatedContent, + options: forwardInResponse, + }; + } + + return updatedContent; + } + + async delete( + ctx: StorageContext, + id: string, + { forwardInResponse, errorToThrow }: { forwardInResponse?: object; errorToThrow?: string } = {} + ) { + // This allows us to test that proper error events are thrown when the storage layer op fails + if (errorToThrow) { + throw new Error(errorToThrow); + } + + if (!this.db.has(id)) { + return { + status: 'error', + error: `Content do delete not found [${id}].`, + }; + } + + this.db.delete(id); + + if (forwardInResponse) { + // We add this so we can test that options are passed down to the storage layer + return { + status: 'success', + options: forwardInResponse, + }; + } + + return { + status: 'success', + }; + } +} + +export const createMemoryStorage = () => { + return new InMemoryStorage(); +}; diff --git a/src/plugins/content_management/server/core/mocks/index.ts b/src/plugins/content_management/server/core/mocks/index.ts new file mode 100644 index 0000000000000..b7f9d8a2f2585 --- /dev/null +++ b/src/plugins/content_management/server/core/mocks/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 { createMemoryStorage } from './in_memory_storage'; +export type { MockContent } from './in_memory_storage'; diff --git a/src/plugins/content_management/server/core/registry.ts b/src/plugins/content_management/server/core/registry.ts new file mode 100644 index 0000000000000..2845ab5f742bc --- /dev/null +++ b/src/plugins/content_management/server/core/registry.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ContentType } from './content_type'; +import { EventBus } from './event_bus'; +import type { ContentStorage, ContentTypeDefinition } from './types'; + +export class ContentRegistry { + private types = new Map(); + + constructor(private eventBus: EventBus) {} + + /** + * Register a new content in the registry. + * + * @param contentType The content type to register + * @param config The content configuration + */ + register(definition: ContentTypeDefinition) { + if (this.types.has(definition.id)) { + throw new Error(`Content [${definition.id}] is already registered`); + } + + const contentType = new ContentType(definition, this.eventBus); + + this.types.set(contentType.id, contentType); + } + + getContentType(id: string): ContentType { + const contentType = this.types.get(id); + if (!contentType) { + throw new Error(`Content [${id}] is not registered.`); + } + return contentType; + } + + /** Get the definition for a specific content type */ + getDefinition(id: string) { + return this.getContentType(id).definition; + } + + /** Get the crud instance of a content type */ + getCrud(id: string) { + return this.getContentType(id).crud; + } + + /** Helper to validate if a content type has been registered */ + isContentRegistered(id: string): boolean { + return this.types.has(id); + } +} diff --git a/src/plugins/content_management/server/core/types.ts b/src/plugins/content_management/server/core/types.ts new file mode 100644 index 0000000000000..4ebd79d605717 --- /dev/null +++ b/src/plugins/content_management/server/core/types.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 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 { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; + +/** Context that is sent to all storage instance methods */ +export interface StorageContext { + requestHandlerContext?: RequestHandlerContext; +} + +export interface ContentStorage { + /** Get a single item */ + get(ctx: StorageContext, id: string, options: unknown): Promise; + + /** Get multiple items */ + bulkGet(ctx: StorageContext, ids: string[], options: unknown): Promise; + + /** Create an item */ + create(ctx: StorageContext, fields: object, options: unknown): Promise; + + /** Update an item */ + update(ctx: StorageContext, id: string, fields: object, options: unknown): Promise; + + /** Delete an item */ + delete(ctx: StorageContext, id: string, options: unknown): Promise; +} + +export interface ContentTypeDefinition { + /** Unique id for the content type */ + id: string; + /** The storage layer for the content. It must implment the ContentStorage interface. */ + storage: S; +} diff --git a/src/plugins/content_management/server/plugin.ts b/src/plugins/content_management/server/plugin.ts index 54ed5ba7a7c2d..5e3ba371a4e16 100755 --- a/src/plugins/content_management/server/plugin.ts +++ b/src/plugins/content_management/server/plugin.ts @@ -6,7 +6,14 @@ * Side Public License, v 1. */ -import type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/server'; +import type { + CoreSetup, + CoreStart, + Plugin, + PluginInitializerContext, + Logger, +} from '@kbn/core/server'; +import { Core } from './core'; import { ContentManagementServerSetup, ContentManagementServerStart, @@ -16,10 +23,20 @@ import { export class ContentManagementPlugin implements Plugin { - constructor(initializerContext: PluginInitializerContext) {} + private readonly logger: Logger; + private readonly core: Core; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + this.core = new Core({ logger: this.logger }); + } public setup(core: CoreSetup) { - return {}; + const { api: coreApi } = this.core.setup(); + + return { + ...coreApi, + }; } public start(core: CoreStart) { diff --git a/src/plugins/content_management/tsconfig.json b/src/plugins/content_management/tsconfig.json index 8a207e0e42ca3..f2cd5ce1b5e59 100644 --- a/src/plugins/content_management/tsconfig.json +++ b/src/plugins/content_management/tsconfig.json @@ -7,6 +7,7 @@ "kbn_references": [ "@kbn/core", "@kbn/config-schema", + "@kbn/core-http-request-handler-context-server", ], "exclude": [ "target/**/*", From 50b83014a3e2947e495c8b0f86aa57078573bd0c Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 14 Feb 2023 13:35:40 +0100 Subject: [PATCH 168/203] [AO] Fix overview alerts loading state (#150868) Fixes #140387 ## Summary Fix alerts table lazy loading state Before ![image](https://user-images.githubusercontent.com/12370520/218094792-24d00334-5414-4737-8f64-d619cbcc9f12.png) After ![image](https://user-images.githubusercontent.com/12370520/218094828-6b3559ce-1f7a-45a7-ae0d-96f5dad141a1.png) --- .../overview_page/overview_page.tsx | 3 ++- .../alert_summary_widget.tsx | 25 +++++------------ .../alert_summary_widget_compact.stories.tsx | 2 +- .../alert_summary_widget_compact.test.tsx | 12 ++++----- .../alert_summary_widget_compact.tsx | 6 ++--- ...alert_summary_widget_full_size.stories.tsx | 2 +- .../alert_summary_widget_full_size.test.tsx | 8 +++--- .../alert_summary_widget_full_size.tsx | 6 ++--- .../alert_summary_widget_loader.tsx | 27 +++++++++++++++++++ .../alert_summary_widget/components/index.ts | 5 ++-- .../public/application/sections/index.tsx | 3 --- .../public/common/get_alerts_table_state.tsx | 8 ++++-- .../public/common/get_rule_alerts_summary.tsx | 14 +++++++--- .../triggers_actions_ui/public/plugin.ts | 7 +++-- .../triggers_actions_ui/public/types.ts | 4 +++ 15 files changed, 83 insertions(+), 49 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_loader.tsx 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 50d4befaefa56..0bad50a97abe6 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 @@ -218,9 +218,10 @@ export function OverviewPage() { - -
- ); + if (isLoading) return ; + if (error) return ; return fullSize ? ( // Only show full size version if there is data activeAlertCount || recoveredAlertCount ? ( - ) : null ) : ( - { - const renderComponent = (props: Partial = {}) => +describe('AlertSummaryWidgetCompact', () => { + const renderComponent = (props: Partial = {}) => render( - { ); - it('should render AlertsSummaryWidgetCompact', async () => { + it('should render AlertSummaryWidgetCompact', async () => { const alertSummaryWidget = renderComponent(); expect(alertSummaryWidget.queryByTestId('alertSummaryWidgetCompact')).toBeTruthy(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_compact.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_compact.tsx index 88e8276f55677..84c47a14a3029 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_compact.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_compact.tsx @@ -14,7 +14,7 @@ import { AlertCounts } from './alert_counts'; import { ALL_ALERT_COLOR, WIDGET_TITLE } from './constants'; import { Alert, ChartThemes } from '../types'; -export interface AlertsSummaryWidgetCompactProps { +export interface AlertSummaryWidgetCompactProps { activeAlertCount: number; activeAlerts: Alert[]; chartThemes: ChartThemes; @@ -23,14 +23,14 @@ export interface AlertsSummaryWidgetCompactProps { onClick: (status?: AlertStatus) => void; } -export const AlertsSummaryWidgetCompact = ({ +export const AlertSummaryWidgetCompact = ({ activeAlertCount, activeAlerts, chartThemes: { theme, baseTheme }, recoveredAlertCount, timeRangeTitle, onClick, -}: AlertsSummaryWidgetCompactProps) => { +}: AlertSummaryWidgetCompactProps) => { const chartTheme = [ theme, EUI_SPARKLINE_THEME_PARTIAL, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.stories.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.stories.tsx index d52bf7ff0a69b..dfdc2d4a26361 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.stories.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.stories.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { AlertsSummaryWidgetFullSize as Component } from './alert_summary_widget_full_size'; +import { AlertSummaryWidgetFullSize as Component } from './alert_summary_widget_full_size'; import { mockedAlertSummaryResponse, mockedChartThemes } from '../../../mock/alert_summary_widget'; export default { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.test.tsx index 9e7b13107cb0a..544cd9c9e1603 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_full_size.test.tsx @@ -8,17 +8,17 @@ import React from 'react'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { - AlertsSummaryWidgetFullSize, - AlertsSummaryWidgetFullSizeProps, + AlertSummaryWidgetFullSize, + AlertSummaryWidgetFullSizeProps, } from './alert_summary_widget_full_size'; import { render } from '@testing-library/react'; import { mockedAlertSummaryResponse, mockedChartThemes } from '../../../mock/alert_summary_widget'; describe('AlertSummaryWidgetFullSize', () => { - const renderComponent = (props: Partial = {}) => + const renderComponent = (props: Partial = {}) => render( - { +}: AlertSummaryWidgetFullSizeProps) => { const chartTheme = [ theme, { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_loader.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_loader.tsx new file mode 100644 index 0000000000000..146e79173fd93 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/alert_summary_widget_loader.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { EuiLoadingChart } from '@elastic/eui'; +import { AlertSummaryWidgetProps } from '..'; + +type Props = Pick; + +export const AlertSummaryWidgetLoader = ({ fullSize }: Props) => { + return ( +
+ +
+ ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/index.ts index 51f94c6915f4c..8e7fe184a10ed 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_summary_widget/components/index.ts @@ -5,6 +5,7 @@ * 2.0. */ -export { AlertsSummaryWidgetCompact } from './alert_summary_widget_compact'; +export { AlertSummaryWidgetCompact } from './alert_summary_widget_compact'; export { AlertSummaryWidgetError } from './alert_summary_widget_error'; -export { AlertsSummaryWidgetFullSize } from './alert_summary_widget_full_size'; +export { AlertSummaryWidgetFullSize } from './alert_summary_widget_full_size'; +export { AlertSummaryWidgetLoader } from './alert_summary_widget_loader'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx index 95ac26d587351..3cab90c72694c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx @@ -58,9 +58,6 @@ export const RuleDefinition = suspendedComponentWithProps( export const RuleTagBadge = suspendedComponentWithProps( lazy(() => import('./rules_list/components/rule_tag_badge')) ); -export const AlertSummaryWidget = suspendedComponentWithProps( - lazy(() => import('./alert_summary_widget/alert_summary_widget')) -); export const RuleStatusPanel = suspendedComponentWithProps( lazy(() => import('./rule_details/components/rule_status_panel')) ); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table_state.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table_state.tsx index d378f26b4c88e..f9f6c37e273a8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table_state.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table_state.tsx @@ -7,6 +7,7 @@ import { EuiLoadingSpinner } from '@elastic/eui'; import React, { lazy, Suspense } from 'react'; +import { LazyLoadProps } from '../types'; import type { AlertsTableStateProps } from '../application/sections/alerts_table/alerts_table_state'; @@ -14,8 +15,11 @@ const AlertsTableStateLazy: React.FC = lazy( () => import('../application/sections/alerts_table/alerts_table_state') ); -export const getAlertsTableStateLazy = (props: AlertsTableStateProps) => ( - }> +export const getAlertsTableStateLazy = ({ + hideLazyLoader, + ...props +}: AlertsTableStateProps & LazyLoadProps) => ( + }> ); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_rule_alerts_summary.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_rule_alerts_summary.tsx index 3f1db7782c2bb..ae7c8462320db 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/get_rule_alerts_summary.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_rule_alerts_summary.tsx @@ -5,10 +5,18 @@ * 2.0. */ -import React from 'react'; -import { AlertSummaryWidget } from '../application/sections'; +import React, { lazy, Suspense } from 'react'; +import { AlertSummaryWidgetLoader } from '../application/sections/alert_summary_widget/components'; import { AlertSummaryWidgetProps } from '../application/sections/alert_summary_widget'; +const AlertSummaryWidgetLazy: React.FC = lazy( + () => import('../application/sections/alert_summary_widget/alert_summary_widget') +); + export const getAlertSummaryWidgetLazy = (props: AlertSummaryWidgetProps) => { - return ; + return ( + }> + + + ); }; diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index 514de57900cc3..010a3e60c95fa 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -47,6 +47,7 @@ import { ExperimentalFeatures, parseExperimentalConfigValue, } from '../common/experimental_features'; +import { LazyLoadProps } from './types'; import type { ActionTypeModel, @@ -111,7 +112,9 @@ export interface TriggersAndActionsUIPublicPluginStart { props: Omit ) => ReactElement; getAlertsTable: (props: AlertsTableProps) => ReactElement; - getAlertsStateTable: (props: AlertsTableStateProps) => ReactElement; + getAlertsStateTable: ( + props: AlertsTableStateProps & LazyLoadProps + ) => ReactElement; getAlertsSearchBar: (props: AlertsSearchBarProps) => ReactElement; getFieldBrowser: (props: FieldBrowserProps) => ReactElement; getRuleStatusDropdown: (props: RuleStatusDropdownProps) => ReactElement; @@ -381,7 +384,7 @@ export class Plugin connectorServices: this.connectorServices!, }); }, - getAlertsStateTable: (props: AlertsTableStateProps) => { + getAlertsStateTable: (props: AlertsTableStateProps & LazyLoadProps) => { return getAlertsTableStateLazy(props); }, getAlertsSearchBar: (props: AlertsSearchBarProps) => { diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index b8157ee5af665..6622b35fa8920 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -666,3 +666,7 @@ export interface UpdateRulesToBulkEditProps { rules?: RuleTableItem[]; filter?: KueryNode | null; } + +export interface LazyLoadProps { + hideLazyLoader?: boolean; +} From 77ed48a75aef947ae4a1a1bb3f58a71538804730 Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 14 Feb 2023 13:37:41 +0100 Subject: [PATCH 169/203] [@kbn/handlebars] Refactor types (#150520) --- packages/kbn-handlebars/index.test.ts | 11 +- packages/kbn-handlebars/index.ts | 9 +- .../kbn-handlebars/src/__jest__/test_bench.ts | 50 ++-- packages/kbn-handlebars/src/handlebars.ts | 14 +- .../src/spec/index.blocks.test.ts | 14 +- .../src/spec/index.data.test.ts | 6 +- .../src/spec/index.helpers.test.ts | 71 +++--- .../src/spec/index.partials.test.ts | 4 +- .../src/spec/index.regressions.test.ts | 14 +- .../src/spec/index.subexpressions.test.ts | 6 +- packages/kbn-handlebars/src/types.ts | 233 ++++++++++++------ packages/kbn-handlebars/src/visitor.ts | 71 +++--- .../drilldowns/url_drilldown/handlebars.ts | 8 +- .../components/lib/replace_vars.ts | 13 +- 14 files changed, 306 insertions(+), 218 deletions(-) diff --git a/packages/kbn-handlebars/index.test.ts b/packages/kbn-handlebars/index.test.ts index d95c6a1c8304a..ed607db1e0bf6 100644 --- a/packages/kbn-handlebars/index.test.ts +++ b/packages/kbn-handlebars/index.test.ts @@ -11,6 +11,7 @@ */ import Handlebars from '.'; +import type { HelperOptions, TemplateDelegate } from './src/types'; import { expectTemplate, forEachCompileFunctionName } from './src/__jest__/test_bench'; it('Handlebars.create', () => { @@ -419,7 +420,7 @@ describe('blocks', () => { .withInput({ me: 'my' }) .withDecorator( 'decorator', - (fn): Handlebars.TemplateDelegate => + (fn): TemplateDelegate => (context, options) => { expect(context).toMatchInlineSnapshot(` Object { @@ -446,7 +447,7 @@ describe('blocks', () => { .withInput({ arr: ['my'] }) .withDecorator( 'decorator', - (fn): Handlebars.TemplateDelegate => + (fn): TemplateDelegate => (context, options) => { expect(context).toMatchInlineSnapshot(`"my"`); expect(options).toMatchInlineSnapshot(` @@ -483,12 +484,12 @@ describe('blocks', () => { it('decorator nested inside of custom helper', () => { expectTemplate('{{#helper}}{{*decorator}}world{{/helper}}') - .withHelper('helper', function (options: Handlebars.HelperOptions) { + .withHelper('helper', function (options: HelperOptions) { return options.fn('my', { foo: 'bar' } as any); }) .withDecorator( 'decorator', - (fn): Handlebars.TemplateDelegate => + (fn): TemplateDelegate => (context, options) => { expect(context).toMatchInlineSnapshot(`"my"`); expect(options).toMatchInlineSnapshot(` @@ -519,7 +520,7 @@ describe('blocks', () => { }) .withDecorator('decorator', (fn) => { const decoratorCallOrder = ++decoratorCall; - const ret: Handlebars.TemplateDelegate = () => { + const ret: TemplateDelegate = () => { const progCallOrder = ++progCall; return `(decorator: ${decoratorCallOrder}, prog: ${progCallOrder}, fn: "${fn()}")`; }; diff --git a/packages/kbn-handlebars/index.ts b/packages/kbn-handlebars/index.ts index a00dbdbb37a64..4e56d27fb438a 100644 --- a/packages/kbn-handlebars/index.ts +++ b/packages/kbn-handlebars/index.ts @@ -24,7 +24,10 @@ export default Handlebars; export const compileFnName: 'compile' | 'compileAST' = allowUnsafeEval() ? 'compile' : 'compileAST'; export type { - DecoratorFunction, - ExtendedCompileOptions, - ExtendedRuntimeOptions, + CompileOptions, + RuntimeOptions, + HelperDelegate, + TemplateDelegate, + DecoratorDelegate, + HelperOptions, } from './src/types'; diff --git a/packages/kbn-handlebars/src/__jest__/test_bench.ts b/packages/kbn-handlebars/src/__jest__/test_bench.ts index fa2626d11fbaf..d17f7f128db2b 100644 --- a/packages/kbn-handlebars/src/__jest__/test_bench.ts +++ b/packages/kbn-handlebars/src/__jest__/test_bench.ts @@ -3,13 +3,13 @@ * See `packages/kbn-handlebars/LICENSE` for more information. */ -import Handlebars from '../..'; -import type { - DecoratorFunction, - DecoratorsHash, - ExtendedCompileOptions, - ExtendedRuntimeOptions, -} from '../types'; +import Handlebars, { + type CompileOptions, + type DecoratorDelegate, + type HelperDelegate, + type RuntimeOptions, +} from '../..'; +import type { DecoratorsHash, HelpersHash, PartialsHash, Template } from '../types'; type CompileFns = 'compile' | 'compileAST'; const compileFns: CompileFns[] = ['compile', 'compileAST']; @@ -40,10 +40,10 @@ export function forEachCompileFunctionName( class HandlebarsTestBench { private template: string; private options: TestOptions; - private compileOptions?: ExtendedCompileOptions; - private runtimeOptions?: ExtendedRuntimeOptions; - private helpers: { [name: string]: Handlebars.HelperDelegate | undefined } = {}; - private partials: { [name: string]: Handlebars.Template } = {}; + private compileOptions?: CompileOptions; + private runtimeOptions?: RuntimeOptions; + private helpers: HelpersHash = {}; + private partials: PartialsHash = {}; private decorators: DecoratorsHash = {}; private input: any = {}; @@ -52,12 +52,12 @@ class HandlebarsTestBench { this.options = options; } - withCompileOptions(compileOptions?: ExtendedCompileOptions) { + withCompileOptions(compileOptions?: CompileOptions) { this.compileOptions = compileOptions; return this; } - withRuntimeOptions(runtimeOptions?: ExtendedRuntimeOptions) { + withRuntimeOptions(runtimeOptions?: RuntimeOptions) { this.runtimeOptions = runtimeOptions; return this; } @@ -67,36 +67,36 @@ class HandlebarsTestBench { return this; } - withHelper(name: string, helper?: F) { + withHelper(name: string, helper: F) { this.helpers[name] = helper; return this; } - withHelpers(helperFunctions: { [name: string]: F }) { + withHelpers(helperFunctions: Record) { for (const [name, helper] of Object.entries(helperFunctions)) { this.withHelper(name, helper); } return this; } - withPartial(name: string | number, partial: Handlebars.Template) { + withPartial(name: string | number, partial: Template) { this.partials[name] = partial; return this; } - withPartials(partials: { [name: string]: Handlebars.Template }) { + withPartials(partials: Record) { for (const [name, partial] of Object.entries(partials)) { this.withPartial(name, partial); } return this; } - withDecorator(name: string, decoratorFunction: DecoratorFunction) { + withDecorator(name: string, decoratorFunction: DecoratorDelegate) { this.decorators[name] = decoratorFunction; return this; } - withDecorators(decoratorFunctions: { [key: string]: DecoratorFunction }) { + withDecorators(decoratorFunctions: Record) { for (const [name, decoratorFunction] of Object.entries(decoratorFunctions)) { this.withDecorator(name, decoratorFunction); } @@ -154,9 +154,9 @@ class HandlebarsTestBench { private compileAndExecuteEval() { const renderEval = this.compileEval(); - const runtimeOptions: ExtendedRuntimeOptions = { - helpers: this.helpers as Record, - partials: this.partials as Record, + const runtimeOptions: RuntimeOptions = { + helpers: this.helpers, + partials: this.partials, decorators: this.decorators, ...this.runtimeOptions, }; @@ -169,9 +169,9 @@ class HandlebarsTestBench { private compileAndExecuteAST() { const renderAST = this.compileAST(); - const runtimeOptions: ExtendedRuntimeOptions = { - helpers: this.helpers as Record, - partials: this.partials as Record, + const runtimeOptions: RuntimeOptions = { + helpers: this.helpers, + partials: this.partials, decorators: this.decorators, ...this.runtimeOptions, }; diff --git a/packages/kbn-handlebars/src/handlebars.ts b/packages/kbn-handlebars/src/handlebars.ts index 91f6f33a6069e..388b331365438 100644 --- a/packages/kbn-handlebars/src/handlebars.ts +++ b/packages/kbn-handlebars/src/handlebars.ts @@ -7,7 +7,7 @@ // https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require import Handlebars from 'handlebars'; -import type { ExtendedCompileOptions, ExtendedRuntimeOptions } from './types'; +import type { CompileOptions, RuntimeOptions, TemplateDelegate } from './types'; import { ElasticHandlebarsVisitor } from './visitor'; const originalCreate = Handlebars.create; @@ -30,15 +30,10 @@ Handlebars.create = function (): typeof Handlebars { return SandboxedHandlebars; }; -/** - * Compiles the given Handlbars template without the use of `eval`. - * - * @returns A render function with the same API as the return value from the regular Handlebars `compile` function. - */ Handlebars.compileAST = function ( input: string | hbs.AST.Program, - options?: ExtendedCompileOptions -) { + options?: CompileOptions +): TemplateDelegate { if (input == null || (typeof input !== 'string' && input.type !== 'Program')) { throw new Handlebars.Exception( `You must pass a string or Handlebars AST to Handlebars.compileAST. You passed ${input}` @@ -48,6 +43,5 @@ Handlebars.compileAST = function ( // If `Handlebars.compileAST` is reassigned, `this` will be undefined. const visitor = new ElasticHandlebarsVisitor(this ?? Handlebars, input, options); - return (context: any, runtimeOptions?: ExtendedRuntimeOptions) => - visitor.render(context, runtimeOptions); + return (context: any, runtimeOptions?: RuntimeOptions) => visitor.render(context, runtimeOptions); }; diff --git a/packages/kbn-handlebars/src/spec/index.blocks.test.ts b/packages/kbn-handlebars/src/spec/index.blocks.test.ts index 18db0a50b6c58..2d9a87078e342 100644 --- a/packages/kbn-handlebars/src/spec/index.blocks.test.ts +++ b/packages/kbn-handlebars/src/spec/index.blocks.test.ts @@ -5,7 +5,7 @@ * See `packages/kbn-handlebars/LICENSE` for more information. */ -import Handlebars from '../..'; +import Handlebars, { type HelperOptions } from '../..'; import { expectTemplate } from '../__jest__/test_bench'; describe('blocks', () => { @@ -200,7 +200,7 @@ describe('blocks', () => { describe('decorators', () => { it('should apply mustache decorators', () => { expectTemplate('{{#helper}}{{*decorator}}{{/helper}}') - .withHelper('helper', function (options: Handlebars.HelperOptions) { + .withHelper('helper', function (options: HelperOptions) { return (options.fn as any).run; }) .withDecorator('decorator', function (fn) { @@ -212,7 +212,7 @@ describe('blocks', () => { it('should apply allow undefined return', () => { expectTemplate('{{#helper}}{{*decorator}}suc{{/helper}}') - .withHelper('helper', function (options: Handlebars.HelperOptions) { + .withHelper('helper', function (options: HelperOptions) { return options.fn() + (options.fn as any).run; }) .withDecorator('decorator', function (fn) { @@ -223,7 +223,7 @@ describe('blocks', () => { it('should apply block decorators', () => { expectTemplate('{{#helper}}{{#*decorator}}success{{/decorator}}{{/helper}}') - .withHelper('helper', function (options: Handlebars.HelperOptions) { + .withHelper('helper', function (options: HelperOptions) { return (options.fn as any).run; }) .withDecorator('decorator', function (fn, props, container, options) { @@ -237,7 +237,7 @@ describe('blocks', () => { expectTemplate( '{{#helper}}{{#*decorator}}{{#*nested}}suc{{/nested}}cess{{/decorator}}{{/helper}}' ) - .withHelper('helper', function (options: Handlebars.HelperOptions) { + .withHelper('helper', function (options: HelperOptions) { return (options.fn as any).run; }) .withDecorators({ @@ -256,7 +256,7 @@ describe('blocks', () => { expectTemplate( '{{#helper}}{{#*decorator}}suc{{/decorator}}{{#*decorator}}cess{{/decorator}}{{/helper}}' ) - .withHelper('helper', function (options: Handlebars.HelperOptions) { + .withHelper('helper', function (options: HelperOptions) { return (options.fn as any).run; }) .withDecorator('decorator', function (fn, props, container, options) { @@ -268,7 +268,7 @@ describe('blocks', () => { it('should access parent variables', () => { expectTemplate('{{#helper}}{{*decorator foo}}{{/helper}}') - .withHelper('helper', function (options: Handlebars.HelperOptions) { + .withHelper('helper', function (options: HelperOptions) { return (options.fn as any).run; }) .withDecorator('decorator', function (fn, props, container, options) { diff --git a/packages/kbn-handlebars/src/spec/index.data.test.ts b/packages/kbn-handlebars/src/spec/index.data.test.ts index 09712223e503f..94d3b51c008aa 100644 --- a/packages/kbn-handlebars/src/spec/index.data.test.ts +++ b/packages/kbn-handlebars/src/spec/index.data.test.ts @@ -5,7 +5,7 @@ * See `packages/kbn-handlebars/LICENSE` for more information. */ -import Handlebars from '../..'; +import Handlebars, { type HelperOptions } from '../..'; import { expectTemplate } from '../__jest__/test_bench'; describe('data', () => { @@ -30,7 +30,7 @@ describe('data', () => { global.kbnHandlebarsEnv = Handlebars.create(); const helpers = Handlebars.createFrame(kbnHandlebarsEnv!.helpers); - helpers.let = function (options: Handlebars.HelperOptions) { + helpers.let = function (options: HelperOptions) { const frame = Handlebars.createFrame(options.data); for (const prop in options.hash) { @@ -138,7 +138,7 @@ describe('data', () => { expectTemplate('{{>myPartial}}') .withCompileOptions({ data: true }) .withPartial('myPartial', '{{hello}}') - .withHelper('hello', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('hello', function (this: any, options: HelperOptions) { return options.data.adjective + ' ' + this.noun; }) .withInput({ noun: 'cat' }) diff --git a/packages/kbn-handlebars/src/spec/index.helpers.test.ts b/packages/kbn-handlebars/src/spec/index.helpers.test.ts index 65d01f72eb701..4cfa39bbb94a9 100644 --- a/packages/kbn-handlebars/src/spec/index.helpers.test.ts +++ b/packages/kbn-handlebars/src/spec/index.helpers.test.ts @@ -5,7 +5,7 @@ * See `packages/kbn-handlebars/LICENSE` for more information. */ -import Handlebars from '../..'; +import Handlebars, { type HelperOptions } from '../..'; import { expectTemplate } from '../__jest__/test_bench'; beforeEach(() => { @@ -32,7 +32,7 @@ describe('helpers', () => { it('helper for raw block gets raw content', () => { expectTemplate('{{{{raw}}}} {{test}} {{{{/raw}}}}') .withInput({ test: 'hello' }) - .withHelper('raw', function (options: Handlebars.HelperOptions) { + .withHelper('raw', function (options: HelperOptions) { return options.fn(); }) .toCompileTo(' {{test}} '); @@ -41,7 +41,7 @@ describe('helpers', () => { it('helper for raw block gets parameters', () => { expectTemplate('{{{{raw 1 2 3}}}} {{test}} {{{{/raw}}}}') .withInput({ test: 'hello' }) - .withHelper('raw', function (a, b, c, options: Handlebars.HelperOptions) { + .withHelper('raw', function (a, b, c, options: HelperOptions) { const ret = options.fn() + a + b + c; return ret; }) @@ -51,7 +51,7 @@ describe('helpers', () => { describe('raw block parsing (with identity helper-function)', () => { function runWithIdentityHelper(template: string, expected: string) { expectTemplate(template) - .withHelper('identity', function (options: Handlebars.HelperOptions) { + .withHelper('identity', function (options: HelperOptions) { return options.fn(); }) .toCompileTo(expected); @@ -95,7 +95,7 @@ describe('helpers', () => { it('helper block with identical context', () => { expectTemplate('{{#goodbyes}}{{name}}{{/goodbyes}}') .withInput({ name: 'Alan' }) - .withHelper('goodbyes', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (this: any, options: HelperOptions) { let out = ''; const byes = ['Goodbye', 'goodbye', 'GOODBYE']; for (let i = 0, j = byes.length; i < j; i++) { @@ -109,7 +109,7 @@ describe('helpers', () => { it('helper block with complex lookup expression', () => { expectTemplate('{{#goodbyes}}{{../name}}{{/goodbyes}}') .withInput({ name: 'Alan' }) - .withHelper('goodbyes', function (options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (options: HelperOptions) { let out = ''; const byes = ['Goodbye', 'goodbye', 'GOODBYE']; for (let i = 0, j = byes.length; i < j; i++) { @@ -126,7 +126,7 @@ describe('helpers', () => { prefix: '/root', goodbyes: [{ text: 'Goodbye', url: 'goodbye' }], }) - .withHelper('link', function (this: any, prefix, options: Handlebars.HelperOptions) { + .withHelper('link', function (this: any, prefix, options: HelperOptions) { return '' + options.fn(this) + ''; }) .toCompileTo('
Goodbye'); @@ -138,7 +138,7 @@ describe('helpers', () => { prefix: '/root', goodbyes: [{ text: 'Goodbye', url: 'goodbye' }], }) - .withHelper('link', function (this: any, prefix, options: Handlebars.HelperOptions) { + .withHelper('link', function (this: any, prefix, options: HelperOptions) { return '' + options.fn(this) + ''; }) .toCompileTo('Goodbye'); @@ -161,7 +161,7 @@ describe('helpers', () => { it('block helper', () => { expectTemplate('{{#goodbyes}}{{text}}! {{/goodbyes}}cruel {{world}}!') .withInput({ world: 'world' }) - .withHelper('goodbyes', function (options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (options: HelperOptions) { return options.fn({ text: 'GOODBYE' }); }) .toCompileTo('GOODBYE! cruel world!'); @@ -170,14 +170,14 @@ describe('helpers', () => { it('block helper staying in the same context', () => { expectTemplate('{{#form}}

{{name}}

{{/form}}') .withInput({ name: 'Yehuda' }) - .withHelper('form', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('form', function (this: any, options: HelperOptions) { return '' + options.fn(this) + ''; }) .toCompileTo('

Yehuda

'); }); it('block helper should have context in this', () => { - function link(this: any, options: Handlebars.HelperOptions) { + function link(this: any, options: HelperOptions) { return '
' + options.fn(this) + ''; } @@ -201,7 +201,7 @@ describe('helpers', () => { it('block helper passing a new context', () => { expectTemplate('{{#form yehuda}}

{{name}}

{{/form}}') .withInput({ yehuda: { name: 'Yehuda' } }) - .withHelper('form', function (context, options: Handlebars.HelperOptions) { + .withHelper('form', function (context, options: HelperOptions) { return '
' + options.fn(context) + '
'; }) .toCompileTo('

Yehuda

'); @@ -210,7 +210,7 @@ describe('helpers', () => { it('block helper passing a complex path context', () => { expectTemplate('{{#form yehuda/cat}}

{{name}}

{{/form}}') .withInput({ yehuda: { name: 'Yehuda', cat: { name: 'Harold' } } }) - .withHelper('form', function (context, options: Handlebars.HelperOptions) { + .withHelper('form', function (context, options: HelperOptions) { return '
' + options.fn(context) + '
'; }) .toCompileTo('

Harold

'); @@ -221,10 +221,10 @@ describe('helpers', () => { .withInput({ yehuda: { name: 'Yehuda' }, }) - .withHelper('link', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('link', function (this: any, options: HelperOptions) { return '' + options.fn(this) + ''; }) - .withHelper('form', function (context, options: Handlebars.HelperOptions) { + .withHelper('form', function (context, options: HelperOptions) { return '
' + options.fn(context) + '
'; }) .toCompileTo('

Yehuda

Hello
'); @@ -232,7 +232,7 @@ describe('helpers', () => { it('block helper inverted sections', () => { const string = "{{#list people}}{{name}}{{^}}Nobody's here{{/list}}"; - function list(this: any, context: any, options: Handlebars.HelperOptions) { + function list(this: any, context: any, options: HelperOptions) { if (context.length > 0) { let out = '
    '; for (let i = 0, j = context.length; i < j; i++) { @@ -477,7 +477,7 @@ describe('helpers', () => { it('block multi-params work', () => { expectTemplate('Message: {{#goodbye cruel world}}{{greeting}} {{adj}} {{noun}}{{/goodbye}}') .withInput({ cruel: 'cruel', world: 'world' }) - .withHelper('goodbye', function (cruel, world, options: Handlebars.HelperOptions) { + .withHelper('goodbye', function (cruel, world, options: HelperOptions) { return options.fn({ greeting: 'Goodbye', adj: cruel, noun: world }); }) .toCompileTo('Message: Goodbye cruel world'); @@ -487,7 +487,7 @@ describe('helpers', () => { describe('hash', () => { it('helpers can take an optional hash', () => { expectTemplate('{{goodbye cruel="CRUEL" world="WORLD" times=12}}') - .withHelper('goodbye', function (options: Handlebars.HelperOptions) { + .withHelper('goodbye', function (options: HelperOptions) { return ( 'GOODBYE ' + options.hash.cruel + @@ -502,7 +502,7 @@ describe('helpers', () => { }); it('helpers can take an optional hash with booleans', () => { - function goodbye(options: Handlebars.HelperOptions) { + function goodbye(options: HelperOptions) { if (options.hash.print === true) { return 'GOODBYE ' + options.hash.cruel + ' ' + options.hash.world; } else if (options.hash.print === false) { @@ -523,7 +523,7 @@ describe('helpers', () => { it('block helpers can take an optional hash', () => { expectTemplate('{{#goodbye cruel="CRUEL" times=12}}world{{/goodbye}}') - .withHelper('goodbye', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('goodbye', function (this: any, options: HelperOptions) { return ( 'GOODBYE ' + options.hash.cruel + @@ -539,7 +539,7 @@ describe('helpers', () => { it('block helpers can take an optional hash with single quoted stings', () => { expectTemplate('{{#goodbye cruel="CRUEL" times=12}}world{{/goodbye}}') - .withHelper('goodbye', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('goodbye', function (this: any, options: HelperOptions) { return ( 'GOODBYE ' + options.hash.cruel + @@ -554,7 +554,7 @@ describe('helpers', () => { }); it('block helpers can take an optional hash with booleans', () => { - function goodbye(this: any, options: Handlebars.HelperOptions) { + function goodbye(this: any, options: HelperOptions) { if (options.hash.print === true) { return 'GOODBYE ' + options.hash.cruel + ' ' + options.fn(this); } else if (options.hash.print === false) { @@ -582,7 +582,7 @@ describe('helpers', () => { it('if a context is not found, custom helperMissing is used', () => { expectTemplate('{{hello}} {{link_to world}}') .withInput({ hello: 'Hello', world: 'world' }) - .withHelper('helperMissing', function (mesg, options: Handlebars.HelperOptions) { + .withHelper('helperMissing', function (mesg, options: HelperOptions) { if (options.name === 'link_to') { return new Handlebars.SafeString('' + mesg + ''); } @@ -593,7 +593,7 @@ describe('helpers', () => { it('if a value is not found, custom helperMissing is used', () => { expectTemplate('{{hello}} {{link_to}}') .withInput({ hello: 'Hello', world: 'world' }) - .withHelper('helperMissing', function (options: Handlebars.HelperOptions) { + .withHelper('helperMissing', function (options: HelperOptions) { if (options.name === 'link_to') { return new Handlebars.SafeString('winning'); } @@ -788,7 +788,7 @@ describe('helpers', () => { it('helpers take precedence over same-named context properties$', () => { expectTemplate('{{#goodbye}} {{cruel world}}{{/goodbye}}') - .withHelper('goodbye', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('goodbye', function (this: any, options: HelperOptions) { return this.goodbye.toUpperCase() + options.fn(this); }) .withHelper('cruel', function (world) { @@ -818,7 +818,7 @@ describe('helpers', () => { it('Scoped names take precedence over block helpers', () => { expectTemplate('{{#goodbye}} {{cruel world}}{{/goodbye}} {{this.goodbye}}') - .withHelper('goodbye', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('goodbye', function (this: any, options: HelperOptions) { return this.goodbye.toUpperCase() + options.fn(this); }) .withHelper('cruel', function (world) { @@ -836,7 +836,7 @@ describe('helpers', () => { it('should take presedence over context values', () => { expectTemplate('{{#goodbyes as |value|}}{{value}}{{/goodbyes}}{{value}}') .withInput({ value: 'foo' }) - .withHelper('goodbyes', function (options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (options: HelperOptions) { expect(options.fn.blockParams).toEqual(1); return options.fn({ value: 'bar' }, { blockParams: [1, 2] }); }) @@ -848,7 +848,7 @@ describe('helpers', () => { .withHelper('value', function () { return 'foo'; }) - .withHelper('goodbyes', function (options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (options: HelperOptions) { expect(options.fn.blockParams).toEqual(1); return options.fn({}, { blockParams: [1, 2] }); }) @@ -861,7 +861,7 @@ describe('helpers', () => { .withHelper('value', function () { return 'foo'; }) - .withHelper('goodbyes', function (this: any, options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (this: any, options: HelperOptions) { expect(options.fn.blockParams).toEqual(1); return options.fn(this, { blockParams: [1, 2] }); }) @@ -879,7 +879,7 @@ describe('helpers', () => { } ) .withInput({ value: 'foo' }) - .withHelper('goodbyes', function (options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (options: HelperOptions) { return options.fn( { value: 'bar' }, { @@ -893,7 +893,7 @@ describe('helpers', () => { it('should allow block params on chained helpers', () => { expectTemplate('{{#if bar}}{{else goodbyes as |value|}}{{value}}{{/if}}{{value}}') .withInput({ value: 'foo' }) - .withHelper('goodbyes', function (options: Handlebars.HelperOptions) { + .withHelper('goodbyes', function (options: HelperOptions) { expect(options.fn.blockParams).toEqual(1); return options.fn({ value: 'bar' }, { blockParams: [1, 2] }); }) @@ -942,12 +942,9 @@ describe('helpers', () => { describe('the lookupProperty-option', () => { it('should be passed to custom helpers', () => { expectTemplate('{{testHelper}}') - .withHelper( - 'testHelper', - function testHelper(this: any, options: Handlebars.HelperOptions) { - return options.lookupProperty(this, 'testProperty'); - } - ) + .withHelper('testHelper', function testHelper(this: any, options: HelperOptions) { + return options.lookupProperty(this, 'testProperty'); + }) .withInput({ testProperty: 'abc' }) .toCompileTo('abc'); }); diff --git a/packages/kbn-handlebars/src/spec/index.partials.test.ts b/packages/kbn-handlebars/src/spec/index.partials.test.ts index fbcf86f8762bf..65930d06c63f7 100644 --- a/packages/kbn-handlebars/src/spec/index.partials.test.ts +++ b/packages/kbn-handlebars/src/spec/index.partials.test.ts @@ -163,8 +163,7 @@ describe('partials', () => { global.kbnHandlebarsEnv = Handlebars.create(); expect(() => { - const undef: unknown = undefined; - kbnHandlebarsEnv!.registerPartial('undefined_test', undef as Handlebars.Template); + kbnHandlebarsEnv!.registerPartial('undefined_test', undefined as any); }).toThrow('Attempting to register a partial called "undefined_test" as undefined'); global.kbnHandlebarsEnv = null; @@ -294,7 +293,6 @@ describe('partials', () => { {}, { partials: { - // @ts-expect-error dude: 'fail', }, } diff --git a/packages/kbn-handlebars/src/spec/index.regressions.test.ts b/packages/kbn-handlebars/src/spec/index.regressions.test.ts index b6785372e5fc5..fc2065fe7585d 100644 --- a/packages/kbn-handlebars/src/spec/index.regressions.test.ts +++ b/packages/kbn-handlebars/src/spec/index.regressions.test.ts @@ -5,7 +5,7 @@ * See `packages/kbn-handlebars/LICENSE` for more information. */ -import Handlebars from '../..'; +import Handlebars, { type HelperOptions } from '../..'; import { expectTemplate, forEachCompileFunctionName } from '../__jest__/test_bench'; describe('Regressions', () => { @@ -99,10 +99,10 @@ describe('Regressions', () => { '{{#inverse}} {{#blk}} Unexpected {{/blk}} {{else}} {{#blk}} Expected {{/blk}} {{/inverse}}'; const helpers = { - blk(block: Handlebars.HelperOptions) { + blk(block: HelperOptions) { return block.fn(''); }, - inverse(block: Handlebars.HelperOptions) { + inverse(block: HelperOptions) { return block.inverse(''); }, }; @@ -204,7 +204,7 @@ describe('Regressions', () => { it('GH-1054: Should handle simple safe string responses', () => { expectTemplate('{{#wrap}}{{>partial}}{{/wrap}}') .withHelpers({ - wrap(options: Handlebars.HelperOptions) { + wrap(options: HelperOptions) { return new Handlebars.SafeString(options.fn()); }, }) @@ -279,7 +279,7 @@ describe('Regressions', () => { ) .withInput({ array: [1], name: 'John' }) .withHelpers({ - myif(conditional, options: Handlebars.HelperOptions) { + myif(conditional, options: HelperOptions) { if (conditional) { return options.fn(this); } else { @@ -325,7 +325,7 @@ describe('Regressions', () => { expectTemplate('{{helpa length="foo"}}') .withInput({ array: [1], name: 'John' }) .withHelpers({ - helpa(options: Handlebars.HelperOptions) { + helpa(options: HelperOptions) { return options.hash.length; }, }) @@ -371,7 +371,7 @@ describe('Regressions', () => { describe("GH-1639: TypeError: Cannot read property 'apply' of undefined\" when handlebars version > 4.6.0 (undocumented, deprecated usage)", () => { it('should treat undefined helpers like non-existing helpers', () => { expectTemplate('{{foo}}') - .withHelper('foo', undefined) + .withHelper('foo', undefined as any) .withInput({ foo: 'bar' }) .toCompileTo('bar'); }); diff --git a/packages/kbn-handlebars/src/spec/index.subexpressions.test.ts b/packages/kbn-handlebars/src/spec/index.subexpressions.test.ts index ccf6402fb3d17..4dee24b78f713 100644 --- a/packages/kbn-handlebars/src/spec/index.subexpressions.test.ts +++ b/packages/kbn-handlebars/src/spec/index.subexpressions.test.ts @@ -5,7 +5,7 @@ * See `packages/kbn-handlebars/LICENSE` for more information. */ -import Handlebars from '../..'; +import Handlebars, { type HelperOptions } from '../..'; import { expectTemplate } from '../__jest__/test_bench'; describe('subexpressions', () => { @@ -102,9 +102,9 @@ describe('subexpressions', () => { }); it('provides each nested helper invocation its own options hash', () => { - let lastOptions: Handlebars.HelperOptions; + let lastOptions: HelperOptions; const helpers = { - equal(x: any, y: any, options: Handlebars.HelperOptions) { + equal(x: any, y: any, options: HelperOptions) { if (!options || options === lastOptions) { throw new Error('options hash was reused'); } diff --git a/packages/kbn-handlebars/src/types.ts b/packages/kbn-handlebars/src/types.ts index fa11a0172e0dc..583170cbe6816 100644 --- a/packages/kbn-handlebars/src/types.ts +++ b/packages/kbn-handlebars/src/types.ts @@ -5,66 +5,67 @@ import { kHelper, kAmbiguous, kSimple } from './symbols'; +// Unexported `CompileOptions` lifted from node_modules/handlebars/types/index.d.ts +// While it could also be extracted using `NonNullable[1]>`, this isn't possible since we declare the handlebars module below +interface HandlebarsCompileOptions { + data?: boolean; + compat?: boolean; + knownHelpers?: KnownHelpers; + knownHelpersOnly?: boolean; + noEscape?: boolean; + strict?: boolean; + assumeObjects?: boolean; + preventIndent?: boolean; + ignoreStandalone?: boolean; + explicitPartialContext?: boolean; +} + /** - * A custom version of the Handlesbars module with an extra `compileAST` function and fixed typings. + * A custom version of the Handlebars module with an extra `compileAST` function and fixed typings. */ declare module 'handlebars' { + /** + * Compiles the given Handlebars template without the use of `eval`. + * + * @returns A render function with the same API as the return value from the regular Handlebars `compile` function. + */ export function compileAST( input: string | hbs.AST.Program, - options?: ExtendedCompileOptions - ): (context?: any, options?: ExtendedRuntimeOptions) => string; + options?: CompileOptions + ): TemplateDelegateFixed; // -------------------------------------------------------- - // Override/Extend inherited types below that are incorrect + // Override/Extend inherited funcions and interfaces below that are incorrect. + // + // Any exported `const` or `type` types can't be overwritten, so we'll just + // have to live with those and cast them to the correct types in our code. + // Some of these fixed types, we'll instead export outside the scope of this + // 'handlebars' module so consumers of @kbn/handlebars at least have a way to + // access the correct types. // -------------------------------------------------------- - export interface TemplateDelegate { - (context?: T, options?: RuntimeOptions): string; // Override to ensure `context` is optional - blockParams?: number; // TODO: Can this really be optional? - partials?: any; // TODO: Narrow type to something better than any? - } - - export interface HelperOptions { - name: string; - loc: { start: hbs.AST.SourceLocation['start']; end: hbs.AST.SourceLocation['end'] }; - lookupProperty: LookupProperty; - } - - export interface HelperDelegate { - // eslint-disable-next-line @typescript-eslint/prefer-function-type - (...params: any[]): any; - } - - export function registerPartial(spec: { [name: string]: Handlebars.Template }): void; // Ensure `spec` object values can be strings -} - -export type NodeType = typeof kHelper | typeof kAmbiguous | typeof kSimple; - -type LookupProperty = (parent: { [name: string]: any }, propertyName: string) => T; - -export type ProcessableStatementNode = - | hbs.AST.MustacheStatement - | hbs.AST.PartialStatement - | hbs.AST.SubExpression; -export type ProcessableBlockStatementNode = hbs.AST.BlockStatement | hbs.AST.PartialBlockStatement; -export type ProcessableNode = ProcessableStatementNode | ProcessableBlockStatementNode; -export type ProcessableNodeWithPathParts = ProcessableNode & { path: hbs.AST.PathExpression }; -export type ProcessableNodeWithPathPartsOrLiteral = ProcessableNode & { - path: hbs.AST.PathExpression | hbs.AST.Literal; -}; - -export interface Helper { - fn?: Handlebars.HelperDelegate; - context: any[]; - params: any[]; - options: AmbiguousHelperOptions; -} - -export type NonBlockHelperOptions = Omit; -export type AmbiguousHelperOptions = Handlebars.HelperOptions | NonBlockHelperOptions; - -export interface DecoratorOptions extends Omit { - args?: any[]; + /** + * A {@link https://handlebarsjs.com/api-reference/helpers.html helper-function} type. + * + * When registering a helper function, it should be of this type. + */ + export interface HelperDelegate extends HelperDelegateFixed {} // eslint-disable-line @typescript-eslint/no-empty-interface + + /** + * A template-function type. + * + * This type is primarily used for the return value of by calls to + * {@link https://handlebarsjs.com/api-reference/compilation.html#handlebars-compile-template-options Handlebars.compile}, + * Handlebars.compileAST and {@link https://handlebarsjs.com/api-reference/compilation.html#handlebars-precompile-template-options Handlebars.template}. + */ + export interface TemplateDelegate extends TemplateDelegateFixed {} // eslint-disable-line @typescript-eslint/no-empty-interface + + /** + * Register one or more {@link https://handlebarsjs.com/api-reference/runtime.html#handlebars-registerpartial-name-partial partials}. + * + * @param spec A key/value object where each key is the name of a partial (a string) and each value is the partial (either a string or a partial function). + */ + export function registerPartial(spec: Record): void; // Ensure `spec` object values can be strings } /** @@ -73,8 +74,8 @@ export interface DecoratorOptions extends Omit; +export interface RuntimeOptions extends Pick { + // The upstream `helpers` property is too loose and allows all functions. + helpers?: HelpersHash; + // The upstream `partials` property is incorrectly typed and doesn't allow + // partials to be strings. + partials?: PartialsHash; + // The upstream `decorators` property is too loose and allows all functions. + decorators?: DecoratorsHash; +} /** - * According to the [decorator docs]{@link https://github.com/handlebars-lang/handlebars.js/blob/4.x/docs/decorators-api.md}, - * a decorator will be called with a different set of arugments than what's actually happening in the upstream code. - * So here I assume that the docs are wrong and that the upstream code is correct. In reality, `context` is the last 4 - * documented arguments rolled into one object. + * The last argument being passed to a helper function is a an {@link https://handlebarsjs.com/api-reference/helpers.html#the-options-parameter options object}. */ -export type DecoratorFunction = ( - prog: Handlebars.TemplateDelegate, +export interface HelperOptions extends Omit { + name: string; + fn: TemplateDelegateFixed; + inverse: TemplateDelegateFixed; + loc: { start: hbs.AST.SourceLocation['start']; end: hbs.AST.SourceLocation['end'] }; + lookupProperty: LookupProperty; +} + +// Use the post-fix `Fixed` to allow us to acces it inside the 'handlebars' module declared above +/** + * A {@link https://handlebarsjs.com/api-reference/helpers.html helper-function} type. + * + * When registering a helper function, it should be of this type. + */ +interface HelperDelegateFixed { + // eslint-disable-next-line @typescript-eslint/prefer-function-type + (...params: any[]): any; +} +export type { HelperDelegateFixed as HelperDelegate }; + +// Use the post-fix `Fixed` to allow us to acces it inside the 'handlebars' module declared above +/** + * A template-function type. + * + * This type is primarily used for the return value of by calls to + * {@link https://handlebarsjs.com/api-reference/compilation.html#handlebars-compile-template-options Handlebars.compile}, + * Handlebars.compileAST and {@link https://handlebarsjs.com/api-reference/compilation.html#handlebars-precompile-template-options Handlebars.template}. + */ +interface TemplateDelegateFixed { + (context?: T, options?: RuntimeOptions): string; // Override to ensure `context` is optional + blockParams?: number; // TODO: Can this really be optional? + partials?: PartialsHash; +} +export type { TemplateDelegateFixed as TemplateDelegate }; + +// According to the decorator docs +// (https://github.com/handlebars-lang/handlebars.js/blob/4.x/docs/decorators-api.md) +// a decorator will be called with a different set of arugments than what's +// actually happening in the upstream code. So here I assume that the docs are +// wrong and that the upstream code is correct. In reality, `context` is the +// last 4 documented arguments rolled into one object. +/** + * A {@link https://github.com/handlebars-lang/handlebars.js/blob/master/docs/decorators-api.md decorator-function} type. + * + * When registering a decorator function, it should be of this type. + */ +export type DecoratorDelegate = ( + prog: TemplateDelegateFixed, props: Record, container: Container, options: any ) => any; -export interface HelpersHash { - [name: string]: Handlebars.HelperDelegate; +// ----------------------------------------------------------------------------- +// INTERNAL TYPES +// ----------------------------------------------------------------------------- + +export type NodeType = typeof kHelper | typeof kAmbiguous | typeof kSimple; + +type LookupProperty = (parent: Record, propertyName: string) => T; + +export type NonBlockHelperOptions = Omit; +export type AmbiguousHelperOptions = HelperOptions | NonBlockHelperOptions; + +export type ProcessableStatementNode = + | hbs.AST.MustacheStatement + | hbs.AST.PartialStatement + | hbs.AST.SubExpression; +export type ProcessableBlockStatementNode = hbs.AST.BlockStatement | hbs.AST.PartialBlockStatement; +export type ProcessableNode = ProcessableStatementNode | ProcessableBlockStatementNode; +export type ProcessableNodeWithPathParts = ProcessableNode & { path: hbs.AST.PathExpression }; +export type ProcessableNodeWithPathPartsOrLiteral = ProcessableNode & { + path: hbs.AST.PathExpression | hbs.AST.Literal; +}; + +export type HelpersHash = Record; +export type PartialsHash = Record; +export type DecoratorsHash = Record; + +// Use the post-fix `Fixed` to allow us to acces it inside the 'handlebars' module declared above +type TemplateFixed = TemplateDelegateFixed | string; +export type { TemplateFixed as Template }; + +export interface DecoratorOptions extends Omit { + args?: any[]; } -export interface PartialsHash { - [name: string]: HandlebarsTemplateDelegate; +export interface VisitorHelper { + fn?: HelperDelegateFixed; + context: any[]; + params: any[]; + options: AmbiguousHelperOptions; } -export interface DecoratorsHash { - [name: string]: DecoratorFunction; +export interface ResolvePartialOptions + extends Omit { + // The upstream `helpers` property is too loose and allows all functions. + helpers?: HelpersHash; + // The upstream `partials` property is incorrectly typed and doesn't allow + // partials to be strings. + partials?: PartialsHash; + // The upstream `decorators` property is too loose and allows all functions. + decorators?: DecoratorsHash; } export interface Container { helpers: HelpersHash; partials: PartialsHash; decorators: DecoratorsHash; - strict: (obj: { [name: string]: any }, name: string, loc: hbs.AST.SourceLocation) => any; + strict: (obj: Record, name: string, loc: hbs.AST.SourceLocation) => any; lookupProperty: LookupProperty; lambda: (current: any, context: any) => any; data: (value: any, depth: number) => any; hooks: { - helperMissing?: Handlebars.HelperDelegate; - blockHelperMissing?: Handlebars.HelperDelegate; + helperMissing?: HelperDelegateFixed; + blockHelperMissing?: HelperDelegateFixed; }; } diff --git a/packages/kbn-handlebars/src/visitor.ts b/packages/kbn-handlebars/src/visitor.ts index c5962f4beb4db..1842c8e5d6a2b 100644 --- a/packages/kbn-handlebars/src/visitor.ts +++ b/packages/kbn-handlebars/src/visitor.ts @@ -18,13 +18,11 @@ import { moveHelperToHooks } from 'handlebars/dist/cjs/handlebars/helpers'; import type { AmbiguousHelperOptions, + CompileOptions, Container, - DecoratorFunction, + DecoratorDelegate, DecoratorsHash, - ExtendedCompileOptions, - ExtendedRuntimeOptions, - Helper, - HelpersHash, + HelperOptions, NodeType, NonBlockHelperOptions, ProcessableBlockStatementNode, @@ -32,6 +30,11 @@ import type { ProcessableNodeWithPathParts, ProcessableNodeWithPathPartsOrLiteral, ProcessableStatementNode, + ResolvePartialOptions, + RuntimeOptions, + Template, + TemplateDelegate, + VisitorHelper, } from './types'; import { kAmbiguous, kHelper, kSimple } from './symbols'; import { @@ -48,8 +51,8 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { private contexts: any[] = []; private output: any[] = []; private template?: string; - private compileOptions: ExtendedCompileOptions; - private runtimeOptions?: ExtendedRuntimeOptions; + private compileOptions: CompileOptions; + private runtimeOptions?: RuntimeOptions; private blockParamNames: any[][] = []; private blockParamValues: any[][] = []; private ast?: hbs.AST.Program; @@ -61,7 +64,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { constructor( env: typeof Handlebars, input: string | hbs.AST.Program, - options: ExtendedCompileOptions = {} + options: CompileOptions = {} ) { super(); @@ -136,18 +139,15 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { }; } - render(context: any, options: ExtendedRuntimeOptions = {}): string { + render(context: any, options: RuntimeOptions = {}): string { this.contexts = [context]; this.output = []; this.runtimeOptions = { ...options }; - this.container.helpers = { - ...this.env.helpers, - ...(options.helpers as HelpersHash), - }; + this.container.helpers = { ...this.env.helpers, ...options.helpers }; this.container.partials = { ...this.env.partials, ...options.partials }; this.container.decorators = { ...(this.env.decorators as DecoratorsHash), - ...(options.decorators as DecoratorsHash), + ...options.decorators, }; this.container.hooks = {}; this.processedRootDecorators = false; @@ -170,7 +170,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { // Generate a "program" function based on the root `Program` in the AST and // call it. This will start the processing of all the child nodes in the // AST. - const defaultMain: Handlebars.TemplateDelegate = (_context) => { + const defaultMain: TemplateDelegate = (_context) => { const prog = this.generateProgramFunction(this.ast!); return prog(_context, this.runtimeOptions); }; @@ -296,7 +296,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { * So we have to look into the program AST body and see if it contains any decorators that we have to process * before we can finish processing of the wrapping program. */ - private processDecorators(program: hbs.AST.Program, prog: Handlebars.TemplateDelegate) { + private processDecorators(program: hbs.AST.Program, prog: TemplateDelegate) { if (!this.processedDecoratorsForProgram.has(program)) { this.processedDecoratorsForProgram.add(program); const props = {}; @@ -312,12 +312,12 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { private processDecorator( decorator: hbs.AST.DecoratorBlock | hbs.AST.Decorator, - prog: Handlebars.TemplateDelegate, + prog: TemplateDelegate, props: Record ) { const options = this.setupDecoratorOptions(decorator); - const result = this.container.lookupProperty( + const result = this.container.lookupProperty( this.container.decorators, options.name )(prog, props, this.container, options); @@ -499,10 +499,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { ? this.resolveNodes(partial.name).join('') : (partial.name as hbs.AST.PathExpression).original; - const options: AmbiguousHelperOptions & Handlebars.ResolvePartialOptions = this.setupParams( - partial, - name - ); + const options: AmbiguousHelperOptions & ResolvePartialOptions = this.setupParams(partial, name); options.helpers = this.container.helpers; options.partials = this.container.partials; options.decorators = this.container.decorators; @@ -516,7 +513,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { // Wrapper function to get access to currentPartialBlock from the closure partialBlock = options.data['partial-block'] = function partialBlockWrapper( context: any, - wrapperOptions: { data?: Handlebars.HelperOptions['data'] } = {} + wrapperOptions: { data?: HelperOptions['data'] } = {} ) { // Restore the partial-block from the closure for the execution of the block // i.e. the part inside the block of the partial call. @@ -542,10 +539,17 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { context = Object.assign({}, context, options.hash); } - const partialTemplate: Handlebars.Template | undefined = + const partialTemplate: Template | undefined = this.container.partials[name] ?? partialBlock ?? - Handlebars.VM.resolvePartial(undefined, undefined, options); + // TypeScript note: We extend ResolvePartialOptions in our types.ts file + // to fix an error in the upstream type. When calling back into the + // upstream code, we just cast back to the non-extended type + Handlebars.VM.resolvePartial( + undefined, + undefined, + options as Handlebars.ResolvePartialOptions + ); if (partialTemplate === undefined) { throw new Handlebars.Exception(`The partial ${name} could not be found`); @@ -619,7 +623,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { } } - private setupHelper(node: ProcessableNode, helperName: string): Helper { + private setupHelper(node: ProcessableNode, helperName: string): VisitorHelper { return { fn: this.container.lookupProperty(this.container.helpers, helperName), context: this.context, @@ -649,11 +653,11 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { return options; } - private setupParams(node: ProcessableBlockStatementNode, name: string): Handlebars.HelperOptions; + private setupParams(node: ProcessableBlockStatementNode, name: string): HelperOptions; private setupParams(node: ProcessableStatementNode, name: string): NonBlockHelperOptions; private setupParams(node: ProcessableNode, name: string): AmbiguousHelperOptions; - private setupParams(node: ProcessableNode, name: string): AmbiguousHelperOptions { - const options = { + private setupParams(node: ProcessableNode, name: string) { + const options: AmbiguousHelperOptions = { name, hash: this.getHash(node), data: this.runtimeOptions!.data, @@ -662,10 +666,10 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { }; if (isBlock(node)) { - (options as Handlebars.HelperOptions).fn = node.program + (options as HelperOptions).fn = node.program ? this.processDecorators(node.program, this.generateProgramFunction(node.program)) : noop; - (options as Handlebars.HelperOptions).inverse = node.inverse + (options as HelperOptions).inverse = node.inverse ? this.processDecorators(node.inverse, this.generateProgramFunction(node.inverse)) : noop; } @@ -676,10 +680,7 @@ export class ElasticHandlebarsVisitor extends Handlebars.Visitor { private generateProgramFunction(program: hbs.AST.Program) { if (!program) return noop; - const prog: Handlebars.TemplateDelegate = ( - nextContext: any, - runtimeOptions: ExtendedRuntimeOptions = {} - ) => { + const prog: TemplateDelegate = (nextContext: any, runtimeOptions: RuntimeOptions = {}) => { runtimeOptions = { ...runtimeOptions }; // inherit data in blockParams from parent program diff --git a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts index 14e1832c48afb..4c8e55c9b3742 100644 --- a/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts +++ b/src/plugins/ui_actions_enhanced/public/drilldowns/url_drilldown/handlebars.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import Handlebars from '@kbn/handlebars'; +import Handlebars, { type HelperOptions, type HelperDelegate } from '@kbn/handlebars'; import { encode } from '@kbn/rison'; import dateMath from '@kbn/datemath'; import moment, { Moment } from 'moment'; @@ -18,9 +18,9 @@ const handlebars = Handlebars.create(); function createSerializationHelper( fnName: string, serializeFn: (value: unknown) => string -): Handlebars.HelperDelegate { +): HelperDelegate { return (...args) => { - const { hash } = args.slice(-1)[0] as Handlebars.HelperOptions; + const { hash } = args.slice(-1)[0] as HelperOptions; const hasHash = Object.keys(hash).length > 0; const hasValues = args.length > 1; if (hasHash && hasValues) { @@ -49,7 +49,7 @@ handlebars.registerHelper( handlebars.registerHelper('date', (...args) => { const values = args.slice(0, -1) as [string | Date, string | undefined]; - const { hash } = args.slice(-1)[0] as Handlebars.HelperOptions; + const { hash } = args.slice(-1)[0] as HelperOptions; // eslint-disable-next-line prefer-const let [date, format] = values; if (typeof date === 'undefined') throw new Error(`[date]: unknown variable`); diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts index 9ae2c6d9c3064..6a53f7c890dcd 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/replace_vars.ts @@ -7,7 +7,12 @@ */ import { encode } from '@kbn/rison'; -import Handlebars, { type ExtendedCompileOptions, compileFnName } from '@kbn/handlebars'; +import Handlebars, { + type CompileOptions, + type HelperOptions, + type HelperDelegate, + compileFnName, +} from '@kbn/handlebars'; import { i18n } from '@kbn/i18n'; import { emptyLabel } from '../../../../common/empty_label'; @@ -16,9 +21,9 @@ const handlebars = Handlebars.create(); function createSerializationHelper( fnName: string, serializeFn: (value: unknown) => string -): Handlebars.HelperDelegate { +): HelperDelegate { return (...args) => { - const { hash } = args.slice(-1)[0] as Handlebars.HelperOptions; + const { hash } = args.slice(-1)[0] as HelperOptions; const hasHash = Object.keys(hash).length > 0; const hasValues = args.length > 1; if (hasHash && hasValues) { @@ -53,7 +58,7 @@ export function replaceVars( str: string, args: Record = {}, vars: Record = {}, - compileOptions: Partial = {} + compileOptions: Partial = {} ) { try { /** we need add '[]' for emptyLabel because this value contains special characters. From 9049386f78f4497cad5cf1994402f1015d95ef68 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Tue, 14 Feb 2023 13:47:26 +0100 Subject: [PATCH 170/203] [Security Solution][Endpoint][Response Actions] Show `outputs` for given list of actions (#151020) ## Summary Adds optional `withOutputs` query param to actions log API that enables `outputs` on actions log for given actions. example API request ```json5 api/endpoint/action?withOutputs=&withOutputs= ``` ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../common/endpoint/schema/actions.test.ts | 55 ++++++++++++++++ .../common/endpoint/schema/actions.ts | 20 ++++++ .../common/endpoint/types/actions.ts | 10 ++- .../routes/actions/list_handler.test.ts | 2 + .../endpoint/routes/actions/list_handler.ts | 2 + .../services/actions/action_list.test.ts | 64 +++++++++++++++++++ .../endpoint/services/actions/action_list.ts | 18 ++++-- .../actions/pending_actions_summary.ts | 31 +++++---- 8 files changed, 180 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/schema/actions.test.ts b/x-pack/plugins/security_solution/common/endpoint/schema/actions.test.ts index 477419213d5c8..e9cab03724c36 100644 --- a/x-pack/plugins/security_solution/common/endpoint/schema/actions.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/schema/actions.test.ts @@ -233,6 +233,61 @@ describe('actions schemas', () => { }); }).not.toThrow(); }); + + it('should not work with only spaces for a string in `withOutputs` list', () => { + expect(() => { + EndpointActionListRequestSchema.query.validate({ + startDate: 'now-1d', // yesterday + endDate: 'now', // today + statuses: ['failed', 'pending', 'successful'], + withOutputs: ' ', + }); + }).toThrow(); + }); + + it('should not work with empty string in `withOutputs` list', () => { + expect(() => { + EndpointActionListRequestSchema.query.validate({ + startDate: 'now-1d', // yesterday + endDate: 'now', // today + statuses: ['failed', 'pending', 'successful'], + withOutputs: '', + }); + }).toThrow(); + }); + + it('should not work with empty strings in `withOutputs` list', () => { + expect(() => { + EndpointActionListRequestSchema.query.validate({ + startDate: 'now-1d', // yesterday + endDate: 'now', // today + statuses: ['failed', 'pending', 'successful'], + withOutputs: ['action-id-1', ' ', 'action-id-2'], + }); + }).toThrow(); + }); + + it('should work with a single action id in `withOutputs` list', () => { + expect(() => { + EndpointActionListRequestSchema.query.validate({ + startDate: 'now-1d', // yesterday + endDate: 'now', // today + statuses: ['failed', 'pending', 'successful'], + withOutputs: 'action-id-1', + }); + }).not.toThrow(); + }); + + it('should work with multiple `withOutputs` filter', () => { + expect(() => { + EndpointActionListRequestSchema.query.validate({ + startDate: 'now-1d', // yesterday + endDate: 'now', // today + statuses: ['failed', 'pending', 'successful'], + withOutputs: ['action-id-1', 'action-id-2'], + }); + }).not.toThrow(); + }); }); describe('NoParametersRequestSchema', () => { diff --git a/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts b/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts index aad6789582923..c6fc2237f9934 100644 --- a/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/schema/actions.ts @@ -131,6 +131,26 @@ export const EndpointActionListRequestSchema = { schema.string({ minLength: 1 }), ]) ), + withOutputs: schema.maybe( + schema.oneOf([ + schema.arrayOf(schema.string({ minLength: 1 }), { + minSize: 1, + validate: (actionIds) => { + if (actionIds.map((v) => v.trim()).some((v) => !v.length)) { + return 'actionIds cannot contain empty strings'; + } + }, + }), + schema.string({ + minLength: 1, + validate: (actionId) => { + if (!actionId.trim().length) { + return 'actionId cannot be an empty string'; + } + }, + }), + ]) + ), }), }; diff --git a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts index 3caf4712f2f44..0a1f482c8583f 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts @@ -371,6 +371,10 @@ export interface ActionDetailsApiResponse< > { data: ActionDetails; } + +/** Action Details normally returned by Action List API response */ +export type ActionDetailsNoOutputs = Omit; + export interface ActionListApiResponse { page: number | undefined; pageSize: number | undefined; @@ -380,11 +384,13 @@ export interface ActionListApiResponse { userIds: string[] | undefined; // users that requested the actions commands: string[] | undefined; // type of actions /** - * The `outputs` is not currently part of the list response due to possibly large amounts of + * Introduced in 8.8, outputs are visible for specific actions like `execute`. + * The `outputs` are part the list response for given set of actions. + * `outputs` for all actions are restricted due to possibly large amounts of * data, especially for cases (in the future) where we might support actions being sent to * multiple agents */ - data: Array>; + data: Array; statuses: ResponseActionStatus[] | undefined; total: number; } diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.test.ts index 7c48c97ab4dfb..b9b67b2197b1d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.test.ts @@ -118,6 +118,7 @@ describe('Action List Handler', () => { it('should correctly format the request when calling `getActionListByStatus`', async () => { await actionListHandler({ + withOutputs: 'actionX', agentIds: 'agentX', commands: 'running-processes', statuses: 'failed', @@ -125,6 +126,7 @@ describe('Action List Handler', () => { }); expect(mockGetActionListByStatus).toBeCalledWith( expect.objectContaining({ + withOutputs: ['actionX'], elasticAgentIds: ['agentX'], commands: ['running-processes'], statuses: ['failed'], diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts index 9566d84898b71..cade342a9fdc3 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/list_handler.ts @@ -56,6 +56,7 @@ export const actionListHandler = ( userIds, commands, statuses, + withOutputs, }, } = req; const esClient = (await context.core).elasticsearch.client.asInternalUser; @@ -72,6 +73,7 @@ export const actionListHandler = ( } const requestParams = { + withOutputs: formatStringIds(withOutputs), commands: formatCommandValues(commands), esClient, elasticAgentIds: formatStringIds(elasticAgentIds), diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts index 4856d00f6e1a4..042a0dd3cd5f4 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.test.ts @@ -116,6 +116,70 @@ describe('When using `getActionList()', () => { }); }); + it('should return expected `output` for given actions', async () => { + const doc = actionRequests.hits.hits[0]._source; + // mock metadataService.findHostMetadataForFleetAgents resolved value + (endpointAppContextService.getEndpointMetadataService as jest.Mock) = jest + .fn() + .mockReturnValue({ + findHostMetadataForFleetAgents: jest.fn().mockResolvedValue([ + { + agent: { + id: 'agent-a', + }, + host: { + hostname: 'Host-agent-a', + }, + }, + ]), + }); + await expect( + getActionList({ + esClient, + logger, + metadataService: endpointAppContextService.getEndpointMetadataService(), + page: 1, + pageSize: 10, + withOutputs: ['123'], + }) + ).resolves.toEqual({ + page: 1, + pageSize: 10, + commands: undefined, + userIds: undefined, + startDate: undefined, + elasticAgentIds: undefined, + endDate: undefined, + data: [ + { + agents: ['agent-a'], + hosts: { 'agent-a': { name: 'Host-agent-a' } }, + command: 'kill-process', + completedAt: '2022-04-30T16:08:47.449Z', + wasSuccessful: true, + errors: undefined, + id: '123', + isCompleted: true, + isExpired: false, + startedAt: '2022-04-27T16:08:47.449Z', + status: 'successful', + outputs: {}, + comment: doc?.EndpointActions.data.comment, + createdBy: doc?.user.id, + parameters: doc?.EndpointActions.data.parameters, + agentState: { + 'agent-a': { + completedAt: '2022-04-30T16:08:47.449Z', + isCompleted: true, + wasSuccessful: true, + }, + }, + }, + ], + total: 1, + }); + }); + it('should return expected output for multiple agent ids', async () => { const agentIds = ['agent-a', 'agent-b', 'agent-x']; actionRequests = createActionRequestsEsSearchResultsMock(agentIds); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts index 28bb43a41919a..f1e6b831cbbce 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/action_list.ts @@ -35,6 +35,8 @@ interface OptionalFilterParams { userIds?: string[]; /** Will filter out the action requests so that only those show `expiration` date is greater than now */ unExpiredOnly?: boolean; + /** list of action Ids that should have outputs */ + withOutputs?: string[]; } /** @@ -55,6 +57,7 @@ export const getActionListByStatus = async ({ statuses, userIds, unExpiredOnly = false, + withOutputs, }: OptionalFilterParams & { statuses: ResponseActionStatus[]; esClient: ElasticsearchClient; @@ -76,6 +79,7 @@ export const getActionListByStatus = async ({ startDate, userIds, unExpiredOnly, + withOutputs, }); // filter out search results based on status filter options @@ -113,6 +117,7 @@ export const getActionList = async ({ startDate, userIds, unExpiredOnly = false, + withOutputs, }: OptionalFilterParams & { esClient: ElasticsearchClient; logger: Logger; @@ -135,6 +140,7 @@ export const getActionList = async ({ startDate, userIds, unExpiredOnly, + withOutputs, }); return { @@ -169,6 +175,7 @@ const getActionDetailsList = async ({ startDate, userIds, unExpiredOnly, + withOutputs, }: GetActionDetailsListParam & { metadataService: EndpointMetadataService }): Promise<{ actionDetails: ActionListApiResponse['data']; totalRecords: number; @@ -260,10 +267,8 @@ const getActionDetailsList = async ({ ); // find the specific response's details using that set of matching responses - const { isCompleted, completedAt, wasSuccessful, errors, agentState } = getActionCompletionInfo( - action.agents, - matchedResponses - ); + const { isCompleted, completedAt, wasSuccessful, errors, agentState, outputs } = + getActionCompletionInfo(action.agents, matchedResponses); const { isExpired, status } = getActionStatus({ expirationDate: action.expiration, @@ -271,9 +276,6 @@ const getActionDetailsList = async ({ wasSuccessful, }); - // NOTE: `outputs` is not returned in this service because including it on a list of data - // could result in a very large response unnecessarily. In the future, we might include - // an option to optionally include it. const actionRecord: ActionListApiResponse['data'][number] = { id: action.id, agents: action.agents, @@ -290,6 +292,8 @@ const getActionDetailsList = async ({ agentState, isExpired, status, + // 8.8 onwards, show outputs only for actions with matching requested action ids + outputs: withOutputs && withOutputs.includes(action.id) ? outputs : undefined, createdBy: action.createdBy, comment: action.comment, parameters: action.parameters, diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/pending_actions_summary.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/pending_actions_summary.ts index e389fc7e8ff93..a2aafaab57d42 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/pending_actions_summary.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/pending_actions_summary.ts @@ -8,7 +8,10 @@ import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { getActionList } from '..'; import type { EndpointMetadataService } from '../metadata'; -import type { ActionDetails, EndpointPendingActions } from '../../../../common/endpoint/types'; +import type { + ActionListApiResponse, + EndpointPendingActions, +} from '../../../../common/endpoint/types'; import { ACTIONS_SEARCH_PAGE_SIZE } from './constants'; const PENDING_ACTION_RESPONSE_MAX_LAPSED_TIME = 300000; // 300k ms === 5 minutes @@ -34,19 +37,21 @@ export const getPendingActionsSummary = async ( }); // Store a map of `agent_id => array of actions` - const unExpiredByAgentId: Record = unExpiredActionList.reduce< - Record - >((byAgentMap, action) => { - for (const agent of action.agents) { - if (!byAgentMap[agent]) { - byAgentMap[agent] = []; - } - - byAgentMap[agent].push(action); - } + const unExpiredByAgentId: Record = + unExpiredActionList.reduce>( + (byAgentMap, action) => { + for (const agent of action.agents) { + if (!byAgentMap[agent]) { + byAgentMap[agent] = []; + } + + byAgentMap[agent].push(action); + } - return byAgentMap; - }, {}); + return byAgentMap; + }, + {} + ); const pending: EndpointPendingActions[] = []; From 58c68c94d47dd6e96c24a053a7530eab52691d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Tue, 14 Feb 2023 13:53:55 +0100 Subject: [PATCH 171/203] [Telemetry] Fix OptedOut banner (#151084) Resolves #135107. --- .../telemetry_notifications.ts | 3 +- .../telemetry_config/get_telemetry_opt_in.ts | 15 +-- .../apis/telemetry/telemetry_config.ts | 101 ++++++++++++-- test/plugin_functional/config.ts | 2 + .../test_suites/telemetry/telemetry.ts | 123 +++++++++++++++--- 5 files changed, 202 insertions(+), 42 deletions(-) diff --git a/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts b/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts index dddaf1259873c..2a3daf14f8414 100644 --- a/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts +++ b/src/plugins/telemetry/public/services/telemetry_notifications/telemetry_notifications.ts @@ -74,7 +74,8 @@ export class TelemetryNotifications { * Should the banner to opt-in be shown to the user? */ public shouldShowOptInBanner = (): boolean => { - const isOptedIn = this.telemetryService.getIsOptedIn(); + // Using `config.optIn` instead of the getter `getIsOptedIn()` because the latter only returns boolean, and we want to compare it against `null`. + const isOptedIn = this.telemetryService.config.optIn; const bannerOnScreen = typeof this.optInBannerId !== 'undefined'; return !bannerOnScreen && isOptedIn === null; }; diff --git a/src/plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts b/src/plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts index 2cc02c15820e1..f949a0e95853b 100644 --- a/src/plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts +++ b/src/plugins/telemetry/server/telemetry_config/get_telemetry_opt_in.ts @@ -29,17 +29,12 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ return configTelemetryOptIn; } - if (typeof telemetrySavedObject.enabled !== 'boolean') { - return configTelemetryOptIn; - } + // If `enabled` is not available in the SO, fall back to the config value. + const savedOptIn = telemetrySavedObject.enabled ?? configTelemetryOptIn; - const savedOptIn = telemetrySavedObject.enabled; - - // if enabled is true, return it + // if the stored value is true, return it if (savedOptIn === true) return savedOptIn; - // TODO: Should we split the logic below into another OptIn getter? - // Additional check if they've already opted out (enabled: false): // - if the Kibana version has changed by at least a minor version, // return null to re-prompt. @@ -49,7 +44,7 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ // if the last kibana version isn't set, or is somehow not a string, return null if (typeof lastKibanaVersion !== 'string') return null; - // if version hasn't changed, just return enabled value + // if version hasn't changed, just return the stored value if (lastKibanaVersion === currentKibanaVersion) return savedOptIn; const lastSemver = parseSemver(lastKibanaVersion); @@ -64,7 +59,7 @@ export const getTelemetryOptIn: GetTelemetryOptIn = ({ if (currentSemver.minor > lastSemver.minor) return null; } - // current version X.Y is not greater than last version X.Y, return enabled + // current version X.Y is not greater than last version X.Y, return the stored value return savedOptIn; }; diff --git a/test/api_integration/apis/telemetry/telemetry_config.ts b/test/api_integration/apis/telemetry/telemetry_config.ts index 57feb849c3468..7a03600a35647 100644 --- a/test/api_integration/apis/telemetry/telemetry_config.ts +++ b/test/api_integration/apis/telemetry/telemetry_config.ts @@ -6,33 +6,38 @@ * Side Public License, v 1. */ +import { AxiosError } from 'axios'; import { FtrProviderContext } from '../../ftr_provider_context'; -export default function optInTest({ getService }: FtrProviderContext) { - const client = getService('es'); +const TELEMETRY_SO_TYPE = 'telemetry'; +const TELEMETRY_SO_ID = 'telemetry'; + +export default function telemetryConfigTest({ getService }: FtrProviderContext) { + const kbnClient = getService('kibanaServer'); const supertest = getService('supertest'); describe('/api/telemetry/v2/config API Telemetry config', () => { before(async () => { - await client.delete( - { - index: '.kibana', - id: 'telemetry:telemetry', - }, - { ignore: [404] } - ); + try { + await kbnClient.savedObjects.delete({ type: TELEMETRY_SO_TYPE, id: TELEMETRY_SO_ID }); + } catch (err) { + const is404Error = err instanceof AxiosError && err.response?.status === 404; + if (!is404Error) { + throw err; + } + } }); it('GET should get the default config', async () => { await supertest.get('/api/telemetry/v2/config').set('kbn-xsrf', 'xxx').expect(200, { allowChangingOptInStatus: true, - optIn: false, // the config.js for this FTR sets it to `false` + optIn: null, // the config.js for this FTR sets it to `false`, we are bound to ask again. sendUsageFrom: 'server', - telemetryNotifyUserAboutOptInDefault: false, // it's not opted-in, so we don't notify about opt-in?? + telemetryNotifyUserAboutOptInDefault: false, // it's not opted-in by default (that's what this flag is about) }); }); - it('GET should get when opted-in', async () => { + it('GET should get `true` when opted-in', async () => { // Opt-in await supertest .post('/api/telemetry/v2/optIn') @@ -44,9 +49,79 @@ export default function optInTest({ getService }: FtrProviderContext) { allowChangingOptInStatus: true, optIn: true, sendUsageFrom: 'server', - // it's not opted-in (in the YAML config) despite being opted-in via API/UI, and we still say false?? telemetryNotifyUserAboutOptInDefault: false, }); }); + + it('GET should get false when opted-out', async () => { + // Opt-in + await supertest + .post('/api/telemetry/v2/optIn') + .set('kbn-xsrf', 'xxx') + .send({ enabled: false }) + .expect(200); + + await supertest.get('/api/telemetry/v2/config').set('kbn-xsrf', 'xxx').expect(200, { + allowChangingOptInStatus: true, + optIn: false, + sendUsageFrom: 'server', + telemetryNotifyUserAboutOptInDefault: false, + }); + }); + + describe('From a previous version', function () { + this.tags(['skipCloud']); + + // Get current values + let attributes: Record; + let currentVersion: string; + let previousMinor: string; + + before(async () => { + [{ attributes }, currentVersion] = await Promise.all([ + kbnClient.savedObjects.get({ type: TELEMETRY_SO_TYPE, id: TELEMETRY_SO_ID }), + kbnClient.version.get(), + ]); + + const [major, minor, patch] = currentVersion.match(/^(\d+)\.(\d+)\.(\d+)/)!.map(parseInt); + previousMinor = `${minor === 0 ? major - 1 : major}.${ + minor === 0 ? minor : minor - 1 + }.${patch}`; + }); + + it('GET should get `true` when opted-in in the current version', async () => { + // Opt-in from a previous version + await kbnClient.savedObjects.create({ + overwrite: true, + type: TELEMETRY_SO_TYPE, + id: TELEMETRY_SO_ID, + attributes: { ...attributes, enabled: true, lastVersionChecked: previousMinor }, + }); + + await supertest.get('/api/telemetry/v2/config').set('kbn-xsrf', 'xxx').expect(200, { + allowChangingOptInStatus: true, + optIn: true, + sendUsageFrom: 'server', + telemetryNotifyUserAboutOptInDefault: false, + }); + }); + + it('GET should get `null` when opted-out in a previous version', async () => { + // Opt-out from previous version + await kbnClient.savedObjects.create({ + overwrite: true, + type: TELEMETRY_SO_TYPE, + id: TELEMETRY_SO_ID, + attributes: { ...attributes, enabled: false, lastVersionChecked: previousMinor }, + }); + + await supertest.get('/api/telemetry/v2/config').set('kbn-xsrf', 'xxx').expect(200, { + allowChangingOptInStatus: true, + optIn: null, + sendUsageFrom: 'server', + telemetryNotifyUserAboutOptInDefault: false, + }); + }); + }); }); } diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts index 4ee09b45e6bdf..fa3e6d072a230 100644 --- a/test/plugin_functional/config.ts +++ b/test/plugin_functional/config.ts @@ -53,6 +53,8 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { '--corePluginDeprecations.noLongerUsed=still_using', // for testing set buffer duration to 0 to immediately flush counters into saved objects. '--usageCollection.usageCounters.bufferDuration=0', + // We want to test when the banner is shown + '--telemetry.banner=true', // explicitly enable the cloud integration plugins to validate the rendered config keys '--xpack.cloud_integrations.chat.enabled=true', '--xpack.cloud_integrations.chat.chatURL=a_string', diff --git a/test/plugin_functional/test_suites/telemetry/telemetry.ts b/test/plugin_functional/test_suites/telemetry/telemetry.ts index 3b087c2705c10..b866733f7f6ce 100644 --- a/test/plugin_functional/test_suites/telemetry/telemetry.ts +++ b/test/plugin_functional/test_suites/telemetry/telemetry.ts @@ -10,36 +10,123 @@ import expect from '@kbn/expect'; import { KBN_SCREENSHOT_MODE_ENABLED_KEY } from '@kbn/screenshot-mode-plugin/public'; import { PluginFunctionalProviderContext } from '../../services'; +const TELEMETRY_SO_TYPE = 'telemetry'; +const TELEMETRY_SO_ID = 'telemetry'; + export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) { + const kbnClient = getService('kibanaServer'); const browser = getService('browser'); + const find = getService('find'); + const supertest = getService('supertest'); const PageObjects = getPageObjects(['common']); describe('Telemetry service', () => { - const checkCanSendTelemetry = (): Promise => { - return browser.executeAsync((cb) => { - (window as unknown as Record Promise>) - ._checkCanSendTelemetry() - .then(cb); + describe('Screenshot mode', () => { + const checkCanSendTelemetry = (): Promise => { + return browser.executeAsync((cb) => { + (window as unknown as Record Promise>) + ._checkCanSendTelemetry() + .then(cb); + }); + }; + + after(async () => { + await browser.removeLocalStorageItem(KBN_SCREENSHOT_MODE_ENABLED_KEY); + await browser.executeAsync((cb) => { + (window as unknown as Record Promise>) + ._resetTelemetry() + .then(() => cb()); + }); }); - }; - after(async () => { - await browser.removeLocalStorageItem(KBN_SCREENSHOT_MODE_ENABLED_KEY); - await browser.executeAsync((cb) => { - (window as unknown as Record Promise>) - ._resetTelemetry() - .then(() => cb()); + it('detects that telemetry cannot be sent in screenshot mode', async () => { + await PageObjects.common.navigateToApp('home'); + expect(await checkCanSendTelemetry()).to.be(true); + + await browser.setLocalStorageItem(KBN_SCREENSHOT_MODE_ENABLED_KEY, 'true'); + await PageObjects.common.navigateToApp('home'); + + expect(await checkCanSendTelemetry()).to.be(false); }); }); - it('detects that telemetry cannot be sent in screenshot mode', async () => { - await PageObjects.common.navigateToApp('home'); - expect(await checkCanSendTelemetry()).to.be(true); + describe('Opt-in/out banners', function () { + this.tags(['skipCloud']); + + // Get current values + let attributes: Record; + let currentVersion: string; + let previousMinor: string; + + before(async () => { + [{ attributes }, currentVersion] = await Promise.all([ + kbnClient.savedObjects.get({ type: TELEMETRY_SO_TYPE, id: TELEMETRY_SO_ID }), + kbnClient.version.get(), + ]); + + const [major, minor, patch] = currentVersion.match(/^(\d+)\.(\d+)\.(\d+)/)!.map(parseInt); + previousMinor = `${minor === 0 ? major - 1 : major}.${ + minor === 0 ? minor : minor - 1 + }.${patch}`; + + await kbnClient.savedObjects.delete({ type: TELEMETRY_SO_TYPE, id: TELEMETRY_SO_ID }); + }); + + it('shows the banner in the default configuration', async () => { + await PageObjects.common.navigateToApp('home'); + expect(await find.existsByCssSelector('[data-test-subj="enable"]')).to.eql(true); + expect(await find.existsByCssSelector('[data-test-subj="disable"]')).to.eql(true); + }); - await browser.setLocalStorageItem(KBN_SCREENSHOT_MODE_ENABLED_KEY, 'true'); - await PageObjects.common.navigateToApp('home'); + it('does not show the banner if opted-in', async () => { + await supertest + .post('/api/telemetry/v2/optIn') + .set('kbn-xsrf', 'xxx') + .send({ enabled: true }) + .expect(200); - expect(await checkCanSendTelemetry()).to.be(false); + await PageObjects.common.navigateToApp('home'); + expect(await find.existsByCssSelector('[data-test-subj="enable"]')).to.eql(false); + expect(await find.existsByCssSelector('[data-test-subj="disable"]')).to.eql(false); + }); + + it('does not show the banner if opted-out in this version', async () => { + await supertest + .post('/api/telemetry/v2/optIn') + .set('kbn-xsrf', 'xxx') + .send({ enabled: false }) + .expect(200); + + await PageObjects.common.navigateToApp('home'); + expect(await find.existsByCssSelector('[data-test-subj="enable"]')).to.eql(false); + expect(await find.existsByCssSelector('[data-test-subj="disable"]')).to.eql(false); + }); + + it('shows the banner if opted-out in a previous version', async () => { + await kbnClient.savedObjects.create({ + overwrite: true, + type: TELEMETRY_SO_TYPE, + id: TELEMETRY_SO_ID, + attributes: { ...attributes, enabled: false, lastVersionChecked: previousMinor }, + }); + + await PageObjects.common.navigateToApp('home'); + expect(await find.existsByCssSelector('[data-test-subj="enable"]')).to.eql(true); + expect(await find.existsByCssSelector('[data-test-subj="disable"]')).to.eql(true); + }); + + it('does not show the banner if opted-in in a previous version', async () => { + await kbnClient.savedObjects.create({ + overwrite: true, + type: TELEMETRY_SO_TYPE, + id: TELEMETRY_SO_ID, + attributes: { ...attributes, enabled: true, lastVersionChecked: previousMinor }, + }); + + await PageObjects.common.navigateToApp('home'); + expect(await find.existsByCssSelector('[data-test-subj="enable"]')).to.eql(false); + expect(await find.existsByCssSelector('[data-test-subj="disable"]')).to.eql(false); + }); }); }); } From 9a52ef4baf07baa8a877252e3a740cfde1624063 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 14 Feb 2023 13:36:17 +0000 Subject: [PATCH 172/203] [Fleet] Fix agent policy selection and creation when there are a large number of agent policies ( > 1k) (#151119) ## Summary Closes #150605 When adding an integration, the agent policy selector (create or select existing agent policy) does not work if there are too many agent policies. In an environment with a large number of agent policies (e.g 1000+) the following API request times out or takes 30 - 60 seconds to respond: ``` http://localhost:5601/mark/api/fleet/agent_policies?page=1&perPage=10000&sortField=name&sortOrder=asc&full=true ``` That is because for each agent policy we get the saved object twice, get ALL package policies, and count the agents, so for 1000 agents we fun 4000 queries using `pmap` in some places. this PR changes it so that we do not get the agent count or `full` agent policy for every agent policy when populating the agent policy select, instead we only get the selected agent policy. This has meant that I have to separately query package policies in order to do the limited packages and APM output checks, but the component now loads instantly on an environment with 3k agent policies. Key changes: - add `noAgentCount` query param to agent policies API, to not count the agents for all agent policies - populate `agents` in the get one agent policy API, this was an inconsistency in our agent policy API - when selecting an existing agent policy, only get the full agent policy for the selected agent policy ###Testing No behaviour should have changed for the agent policy select, some niche behaviour of the selector: - if adding the APM integration, any agent policy with a logstash output configured for integration data should be disabled - if adding a limited integration e.g apm or defend, any agent policy already containing that integration should be disabled Screenshot 2023-02-14 at 10 45 03 --- .../plugins/fleet/common/openapi/bundled.json | 8 ++ .../plugins/fleet/common/openapi/bundled.yaml | 9 ++ .../common/openapi/paths/agent_policies.yaml | 5 + .../common/types/rest_spec/agent_policy.ts | 1 + .../steps/step_select_agent_policy.tsx | 100 +++++++++++------- .../components/steps/step_select_hosts.tsx | 3 +- .../server/routes/agent_policy/handlers.ts | 12 ++- .../server/types/rest_spec/agent_policy.ts | 1 + 8 files changed, 97 insertions(+), 42 deletions(-) diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index 041c757075bbf..f535bad37c6c2 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -2522,6 +2522,14 @@ "in": "query", "name": "full", "description": "When set to true, retrieve the related package policies for each agent policy." + }, + { + "schema": { + "type": "boolean" + }, + "in": "query", + "name": "noAgentCount", + "description": "When set to true, do not count how many agents are in the agent policy, this can improve performance if you are searching over a large number of agent policies. The \"agents\" property will always be 0 if set to true." } ], "description": "" diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 576cc240f64bf..7dcc4ba9610d2 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -1558,6 +1558,15 @@ paths: description: >- When set to true, retrieve the related package policies for each agent policy. + - schema: + type: boolean + in: query + name: noAgentCount + description: >- + When set to true, do not count how many agents are in the agent + policy, this can improve performance if you are searching over a + large number of agent policies. The "agents" property will always be + 0 if set to true. description: '' post: summary: Agent policy - Create diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml index d431024445656..eb701057c2953 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml @@ -34,6 +34,11 @@ get: in: query name: full description: When set to true, retrieve the related package policies for each agent policy. + - schema: + type: boolean + in: query + name: noAgentCount + description: When set to true, do not count how many agents are in the agent policy, this can improve performance if you are searching over a large number of agent policies. The "agents" property will always be 0 if set to true. description: '' post: diff --git a/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts index a62b1a1b9e4e6..738a8201b14a1 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/agent_policy.ts @@ -11,6 +11,7 @@ import type { ListResult, ListWithKuery, BulkGetResult } from './common'; export interface GetAgentPoliciesRequest { query: ListWithKuery & { + noAgentCount?: boolean; full?: boolean; }; } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx index cef02bfdc84da..718392ca8e2b1 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx @@ -22,23 +22,20 @@ import { } from '@elastic/eui'; import { Error } from '../../../../../components'; -import type { - AgentPolicy, - Output, - PackageInfo, - GetAgentPoliciesResponseItem, -} from '../../../../../types'; +import type { AgentPolicy, Output, PackageInfo } from '../../../../../types'; import { isPackageLimited, doesAgentPolicyAlreadyIncludePackage } from '../../../../../services'; import { useGetAgentPolicies, useGetOutputs, sendGetOneAgentPolicy, useFleetStatus, + useGetPackagePolicies, } from '../../../../../hooks'; import { FLEET_APM_PACKAGE, SO_SEARCH_LIMIT, outputType, + PACKAGE_POLICY_SAVED_OBJECT_TYPE, } from '../../../../../../../../common/constants'; const AgentPolicyFormRow = styled(EuiFormRow)` @@ -58,22 +55,36 @@ function useAgentPoliciesOptions(packageInfo?: PackageInfo) { perPage: SO_SEARCH_LIMIT, sortField: 'name', sortOrder: 'asc', - full: true, + noAgentCount: true, // agentPolicy.agents will always be 0 + full: false, // package_policies will always be empty }); const agentPolicies = useMemo( () => agentPoliciesData?.items.filter((policy) => !policy.is_managed) || [], [agentPoliciesData?.items] ); - const agentPoliciesById = useMemo(() => { - return agentPolicies.reduce((acc: { [key: string]: GetAgentPoliciesResponseItem }, policy) => { - acc[policy.id] = policy; - return acc; - }, {}); - }, [agentPolicies]); - const { data: outputsData, isLoading: isOutputLoading } = useGetOutputs(); + // get all package policies with apm integration or the current integration + const { data: packagePoliciesForThisPackage, isLoading: isLoadingPackagePolicies } = + useGetPackagePolicies({ + page: 1, + perPage: SO_SEARCH_LIMIT, + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name: ${packageInfo?.name}`, + }); + + const packagePoliciesForThisPackageByAgentPolicyId = useMemo( + () => + packagePoliciesForThisPackage?.items.reduce( + (acc: { [key: string]: boolean }, packagePolicy) => { + acc[packagePolicy.policy_id] = true; + return acc; + }, + {} + ), + [packagePoliciesForThisPackage?.items] + ); + const { getDataOutputForPolicy } = useMemo(() => { const defaultOutput = (outputsData?.items ?? []).find((output) => output.is_default); const outputsById = (outputsData?.items ?? []).reduce( @@ -85,7 +96,7 @@ function useAgentPoliciesOptions(packageInfo?: PackageInfo) { ); return { - getDataOutputForPolicy: (policy: AgentPolicy) => { + getDataOutputForPolicy: (policy: Pick) => { return policy.data_output_id ? outputsById[policy.data_output_id] : defaultOutput; }, }; @@ -94,20 +105,19 @@ function useAgentPoliciesOptions(packageInfo?: PackageInfo) { const agentPolicyOptions: Array> = useMemo( () => packageInfo - ? agentPolicies.map((agentConf) => { - const isLimitedPackageAlreadyInPolicy = doesAgentPolicyHaveLimitedPackage( - agentConf, - packageInfo - ); + ? agentPolicies.map((policy) => { + const isLimitedPackageAlreadyInPolicy = + isPackageLimited(packageInfo) && + packagePoliciesForThisPackageByAgentPolicyId?.[policy.id]; const isAPMPackageAndDataOutputIsLogstash = - packageInfo.name === FLEET_APM_PACKAGE && - getDataOutputForPolicy(agentConf)?.type === outputType.Logstash; + packageInfo?.name === FLEET_APM_PACKAGE && + getDataOutputForPolicy(policy)?.type === outputType.Logstash; return { inputDisplay: ( <> - {agentConf.name} + {policy.name} {isAPMPackageAndDataOutputIsLogstash && ( <> @@ -121,21 +131,25 @@ function useAgentPoliciesOptions(packageInfo?: PackageInfo) { )} ), - value: agentConf.id, + value: policy.id, disabled: isLimitedPackageAlreadyInPolicy || isAPMPackageAndDataOutputIsLogstash, 'data-test-subj': 'agentPolicyItem', }; }) : [], - [agentPolicies, packageInfo, getDataOutputForPolicy] + [ + packageInfo, + agentPolicies, + packagePoliciesForThisPackageByAgentPolicyId, + getDataOutputForPolicy, + ] ); return { agentPoliciesError, - isLoading: isOutputLoading || isAgentPoliciesLoading, - agentPolicies, - agentPoliciesById, + isLoading: isOutputLoading || isAgentPoliciesLoading || isLoadingPackagePolicies, agentPolicyOptions, + agentPolicies, }; } @@ -154,7 +168,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ }> = ({ packageInfo, agentPolicy, - updateAgentPolicy, + updateAgentPolicy: updateSelectedAgentPolicy, setHasAgentPolicyError, selectedAgentPolicyId, }) => { @@ -162,7 +176,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ const [selectedAgentPolicyError, setSelectedAgentPolicyError] = useState(); - const { agentPolicies, agentPoliciesById, isLoading, agentPoliciesError, agentPolicyOptions } = + const { isLoading, agentPoliciesError, agentPolicyOptions, agentPolicies } = useAgentPoliciesOptions(packageInfo); // Selected agent policy state const [selectedPolicyId, setSelectedPolicyId] = useState( @@ -170,10 +184,23 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ (selectedAgentPolicyId || (agentPolicies.length === 1 ? agentPolicies[0].id : undefined)) ); + const [isLoadingSelectedAgentPolicy, setIsLoadingSelectedAgentPolicy] = useState(false); + const [selectedAgentPolicy, setSelectedAgentPolicy] = useState( + agentPolicy + ); + + const updateAgentPolicy = useCallback( + (selectedPolicy: AgentPolicy | undefined) => { + setSelectedAgentPolicy(selectedPolicy); + updateSelectedAgentPolicy(selectedPolicy); + }, + [updateSelectedAgentPolicy] + ); // Update parent selected agent policy state useEffect(() => { const fetchAgentPolicyInfo = async () => { if (selectedPolicyId) { + setIsLoadingSelectedAgentPolicy(true); const { data, error } = await sendGetOneAgentPolicy(selectedPolicyId); if (error) { setSelectedAgentPolicyError(error); @@ -182,6 +209,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ setSelectedAgentPolicyError(undefined); updateAgentPolicy(data.item); } + setIsLoadingSelectedAgentPolicy(false); } else { setSelectedAgentPolicyError(undefined); updateAgentPolicy(undefined); @@ -268,12 +296,12 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ } helpText={ - isFleetReady && selectedPolicyId ? ( + isFleetReady && selectedPolicyId && !isLoadingSelectedAgentPolicy ? ( ) : null @@ -281,10 +309,8 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ isInvalid={Boolean( !selectedPolicyId || !packageInfo || - doesAgentPolicyHaveLimitedPackage( - agentPoliciesById[selectedPolicyId], - packageInfo - ) + (selectedAgentPolicy && + doesAgentPolicyHaveLimitedPackage(selectedAgentPolicy, packageInfo)) )} error={ !selectedPolicyId ? ( @@ -308,7 +334,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ } )} fullWidth - isLoading={isLoading || !packageInfo} + isLoading={isLoading || !packageInfo || isLoadingSelectedAgentPolicy} options={agentPolicyOptions} valueOfSelected={selectedPolicyId} onChange={onChange} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx index 992501e012a8b..87ef9ac864bfd 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_hosts.tsx @@ -64,7 +64,8 @@ export const StepSelectHosts: React.FunctionComponent = ({ perPage: SO_SEARCH_LIMIT, sortField: 'name', sortOrder: 'asc', - full: true, + full: false, // package_policies will always be empty + noAgentCount: true, // agentPolicy.agents will always be 0 }); if (err) { // eslint-disable-next-line no-console diff --git a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts index 9da77a9bed210..505f5e1b89b0a 100644 --- a/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent_policy/handlers.ts @@ -75,7 +75,7 @@ export const getAgentPoliciesHandler: FleetRequestHandler< const fleetContext = await context.fleet; const soClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; - const { full: withPackagePolicies = false, ...restOfQuery } = request.query; + const { full: withPackagePolicies = false, noAgentCount = false, ...restOfQuery } = request.query; try { const { items, total, page, perPage } = await agentPolicyService.list(soClient, { withPackagePolicies, @@ -88,9 +88,11 @@ export const getAgentPoliciesHandler: FleetRequestHandler< page, perPage, }; - - await populateAssignedAgentsCount(esClient, soClient, items); - + if (!noAgentCount) { + await populateAssignedAgentsCount(esClient, soClient, items); + } else { + items.forEach((item) => (item.agents = 0)); + } return response.ok({ body }); } catch (error) { return defaultFleetErrorHandler({ error, response }); @@ -136,10 +138,12 @@ export const getOneAgentPolicyHandler: RequestHandler< TypeOf > = async (context, request, response) => { const coreContext = await context.core; + const esClient = coreContext.elasticsearch.client.asInternalUser; const soClient = coreContext.savedObjects.client; try { const agentPolicy = await agentPolicyService.get(soClient, request.params.agentPolicyId); if (agentPolicy) { + await populateAssignedAgentsCount(esClient, soClient, [agentPolicy]); const body: GetOneAgentPolicyResponse = { item: agentPolicy, }; diff --git a/x-pack/plugins/fleet/server/types/rest_spec/agent_policy.ts b/x-pack/plugins/fleet/server/types/rest_spec/agent_policy.ts index c2599d79b3364..25275ed998c58 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/agent_policy.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/agent_policy.ts @@ -13,6 +13,7 @@ import { ListWithKuerySchema, BulkRequestBodySchema } from './common'; export const GetAgentPoliciesRequestSchema = { query: ListWithKuerySchema.extends({ + noAgentCount: schema.maybe(schema.boolean()), full: schema.maybe(schema.boolean()), }), }; From 49d7a2540d2355950aa3b0a56d9db1737f242bd5 Mon Sep 17 00:00:00 2001 From: Andrew Macri Date: Tue, 14 Feb 2023 06:41:07 -0700 Subject: [PATCH 173/203] [Security Solution] Fixes Data Quality dashboard integration issues (#151071) ## [Security Solution] Fixes Data Quality dashboard integration issues This PR implements fixes for the following issues observed during integration testing: - [[Security Solution] Data Quality dashboard: read Docs count from primaries.docs.count](https://github.com/elastic/kibana/issues/151061) `issue 151061` - [[Security Solution] Display a Remote clusters won't be checked message, and remove the text read_cross_cluster from error messages](https://github.com/elastic/kibana/issues/151063) `issue 151063` - This PR also updates the `getFieldTypes` function to fix an issue where, (for example), a field named `some.field.keyword` would be expanded as `some.field.fields.keyword`. ### Desk testing - See the details of the issues above for reproduction / desk testing steps --- .../errors_popover/index.tsx | 2 +- .../errors_popover/translations.ts | 7 - .../error_empty_prompt/index.tsx | 2 +- .../index_properties/markdown/helpers.ts | 3 +- .../data_quality_panel/pattern/index.test.tsx | 73 +++ .../data_quality_panel/pattern/index.tsx | 8 + .../remote_clusters_callout/index.test.tsx | 22 + .../remote_clusters_callout/index.tsx | 21 + .../remote_clusters_callout/translations.ts | 20 + .../impl/data_quality/helpers.test.ts | 279 ++++++++- .../impl/data_quality/helpers.ts | 6 +- .../mock/stats/mock_stats_green_index.ts | 293 +++++++++ .../mock/stats/mock_stats_yellow_index.tsx | 568 ++++++++++++++++++ .../mock/test_providers/index.tsx | 28 + .../jest.config.js | 1 + .../setup_tests.ts | 9 + .../tsconfig.json | 1 + 17 files changed, 1318 insertions(+), 25 deletions(-) create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.test.tsx create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.test.tsx create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.tsx create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/translations.ts create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_green_index.ts create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_yellow_index.tsx create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/test_providers/index.tsx create mode 100644 x-pack/packages/kbn-ecs-data-quality-dashboard/setup_tests.ts diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/index.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/index.tsx index b24c7e6cd598c..b9e0fc61ec545 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/index.tsx +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/index.tsx @@ -92,7 +92,7 @@ const ErrorsPopoverComponent: React.FC = ({ addSuccessToast, errorSummary {i18n.VIEW_INDEX_METADATA}
  • - {i18n.READ} {i18n.OR} {i18n.READ_CROSS_CLUSTER} + {i18n.READ}
diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/translations.ts b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/translations.ts index e6c9459d308e9..304ce658a0704 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/translations.ts +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/data_quality_summary/errors_popover/translations.ts @@ -56,13 +56,6 @@ export const READ = i18n.translate('ecsDataQualityDashboard.errors.read', { defaultMessage: 'read', }); -export const READ_CROSS_CLUSTER = i18n.translate( - 'ecsDataQualityDashboard.errors.readCrossCluster', - { - defaultMessage: 'read_cross_cluster', - } -); - export const THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED = i18n.translate( 'ecsDataQualityDashboard.errors.theFollowingPrivilegesLabel', { diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/error_empty_prompt/index.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/error_empty_prompt/index.tsx index 9a81fcd9ad7e6..a0b70daee0e40 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/error_empty_prompt/index.tsx +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/error_empty_prompt/index.tsx @@ -27,7 +27,7 @@ const ErrorEmptyPromptComponent: React.FC = ({ title }) => ( {i18n.VIEW_INDEX_METADATA}
  • - {i18n.READ} {i18n.OR} {i18n.READ_CROSS_CLUSTER} + {i18n.READ}
  • diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts index a4df52d02ca58..7d8d7ca03f084 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/index_properties/markdown/helpers.ts @@ -14,7 +14,6 @@ import { MONITOR, OR, READ, - READ_CROSS_CLUSTER, THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED, VIEW_INDEX_METADATA, } from '../../data_quality_summary/errors_popover/translations'; @@ -178,7 +177,7 @@ ${ERRORS_MAY_OCCUR} ${THE_FOLLOWING_PRIVILEGES_ARE_REQUIRED} - \`${MONITOR}\` ${OR} \`${MANAGE}\` - \`${VIEW_INDEX_METADATA}\` -- \`${READ}\` ${OR} \`${READ_CROSS_CLUSTER}\` +- \`${READ}\` ${getMarkdownTableHeader(headerNames)} ${getMarkdownTableRows(errorSummary)} diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.test.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.test.tsx new file mode 100644 index 0000000000000..4fa3b34884929 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.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 { DARK_THEME } from '@elastic/charts'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../mock/test_providers'; +import { Pattern } from '.'; + +jest.mock('../../use_stats', () => ({ + useStats: jest.fn(() => ({ + stats: {}, + error: null, + loading: false, + })), +})); + +jest.mock('../../use_ilm_explain', () => ({ + useIlmExplain: jest.fn(() => ({ + error: null, + ilmExplain: {}, + loading: false, + })), +})); + +const defaultProps = { + addSuccessToast: jest.fn(), + canUserCreateAndReadCases: jest.fn(), + defaultNumberFormat: '0,0.[000]', + getGroupByFieldsOnClick: jest.fn(), + ilmPhases: ['hot', 'warm', 'unmanaged'], + indexNames: undefined, + openCreateCaseFlyout: jest.fn(), + patternRollup: undefined, + theme: DARK_THEME, + updatePatternIndexNames: jest.fn(), + updatePatternRollup: jest.fn(), +}; + +describe('pattern', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + test('it renders the remote clusters callout when the pattern includes a colon', () => { + const pattern = 'remote:*'; // <-- a colon in the pattern indicates the use of cross cluster search + + render( + + + + ); + + expect(screen.getByTestId('remoteClustersCallout')).toBeInTheDocument(); + }); + + test('it does NOT render the remote clusters callout when the pattern does NOT include a colon', () => { + const pattern = 'auditbeat-*'; // <-- no colon in the pattern + + render( + + + + ); + + expect(screen.queryByTestId('remoteClustersCallout')).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx index d6a73f1fd2cfb..bd6479490dab8 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/pattern/index.tsx @@ -37,6 +37,7 @@ import { import { IndexProperties } from '../index_properties'; import { LoadingEmptyPrompt } from '../loading_empty_prompt'; import { PatternSummary } from './pattern_summary'; +import { RemoteClustersCallout } from '../remote_clusters_callout'; import { SummaryTable } from '../summary_table'; import { getSummaryTableColumns } from '../summary_table/helpers'; import * as i18n from './translations'; @@ -227,6 +228,13 @@ const PatternComponent: React.FC = ({ + {!loading && pattern.includes(':') && ( + <> + + + + )} + {!loading && error != null && ( )} diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.test.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.test.tsx new file mode 100644 index 0000000000000..00bbab3b38537 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.test.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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TITLE, TO_CHECK_INDICES_ON_REMOTE_CLUSTERS } from './translations'; +import { RemoteClustersCallout } from '.'; + +describe('RemoteClustersCallout', () => { + test('it renders the expected content', () => { + render(); + + expect(screen.getByTestId('remoteClustersCallout')).toHaveTextContent( + `${TITLE}${TO_CHECK_INDICES_ON_REMOTE_CLUSTERS}` + ); + }); +}); diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.tsx new file mode 100644 index 0000000000000..d7ad6408b4bb2 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/index.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 { EuiCallOut } from '@elastic/eui'; +import React from 'react'; + +import * as i18n from './translations'; + +const RemoteClustersCalloutComponent: React.FC = () => ( + +

    {i18n.TO_CHECK_INDICES_ON_REMOTE_CLUSTERS}

    +
    +); + +RemoteClustersCalloutComponent.displayName = 'RemoteClustersCalloutComponent'; + +export const RemoteClustersCallout = React.memo(RemoteClustersCalloutComponent); diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/translations.ts b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/translations.ts new file mode 100644 index 0000000000000..549bcb1fec487 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/data_quality_panel/remote_clusters_callout/translations.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 { i18n } from '@kbn/i18n'; + +export const TITLE = i18n.translate('ecsDataQualityDashboard.remoteClustersCallout.title', { + defaultMessage: "Remote clusters won't be checked", +}); + +export const TO_CHECK_INDICES_ON_REMOTE_CLUSTERS = i18n.translate( + 'ecsDataQualityDashboard.remoteClustersCallout.toCheckIndicesOnRemoteClustersLabel', + { + defaultMessage: + "To check indices on remote clusters supporting cross-cluster search, login to the remote cluster's Kibana", + } +); diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.test.ts b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.test.ts index c44104451b1d8..b9feec8a04f99 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.test.ts +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.test.ts @@ -5,24 +5,281 @@ * 2.0. */ -import { getIncompatibleStatColor } from './helpers'; +import { MappingProperty } from '@elastic/elasticsearch/lib/api/types'; +import { + getDocsCount, + getFieldTypes, + getIncompatibleStatColor, + getTotalDocsCount, +} from './helpers'; +import { mockStatsGreenIndex } from './mock/stats/mock_stats_green_index'; +import { mockStatsYellowIndex } from './mock/stats/mock_stats_yellow_index'; -describe('getIncompatibleStatColor', () => { - test('it returns the expected color when incompatible is greater than zero', () => { - const incompatible = 123; +describe('helpers', () => { + describe('getFieldTypes', () => { + /** + * These `mappingsProperties` represent mappings that were generated by + * Elasticsearch automatically, for an index named `auditbeat-custom-index-1`: + * + * ``` + * DELETE auditbeat-custom-index-1 + * + * PUT auditbeat-custom-index-1 + * + * PUT auditbeat-custom-index-1/_mapping + * { + * "properties": { + * "@timestamp": { + * "type": "date" + * }, + * "event.category": { + * "type": "keyword", + * "ignore_above": 1024 + * } + * } + * } + * ``` + * + * when the following document was inserted: + * + * ``` + * POST auditbeat-custom-index-1/_doc + * { + * "@timestamp": "2023-02-06T09:41:49.668Z", + * "host": { + * "name": "foo" + * }, + * "event": { + * "category": "an_invalid_category" + * }, + * "some.field": "this", + * "source": { + * "port": 90210, + * "ip": "10.1.2.3" + * } + * } + * ``` + */ + const mappingsProperties: Record = { + '@timestamp': { + type: 'date', + }, + event: { + properties: { + category: { + type: 'keyword', + ignore_above: 1024, + }, + }, + }, + host: { + properties: { + name: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + }, + }, + some: { + properties: { + field: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + }, + }, + source: { + properties: { + ip: { + type: 'text', + fields: { + keyword: { + type: 'keyword', + ignore_above: 256, + }, + }, + }, + port: { + type: 'long', + }, + }, + }, + }; - expect(getIncompatibleStatColor(incompatible)).toBe('#bd271e'); + const expected = [ + { + field: '@timestamp', + type: 'date', + }, + { + field: 'event.category', + type: 'keyword', + }, + { + field: 'host.name', + type: 'text', + }, + { + field: 'host.name.keyword', + type: 'keyword', + }, + { + field: 'some.field', + type: 'text', + }, + { + field: 'some.field.keyword', + type: 'keyword', + }, + { + field: 'source.ip', + type: 'text', + }, + { + field: 'source.ip.keyword', + type: 'keyword', + }, + { + field: 'source.port', + type: 'long', + }, + ]; + + test('it flattens the field names and types in the mapping properties', () => { + expect(getFieldTypes(mappingsProperties)).toEqual(expected); + }); + + test('it throws a type error when mappingsProperties is not flatten-able', () => { + // @ts-expect-error + const invalidType: Record = []; // <-- this is an array, NOT a valid Record + + expect(() => getFieldTypes(invalidType)).toThrowError('Root value is not flatten-able'); + }); }); - test('it returns undefined when incompatible is zero', () => { - const incompatible = 0; + describe('getDocsCount', () => { + test('it returns the expected docs count when `stats` contains the `indexName`', () => { + const indexName = '.ds-packetbeat-8.6.1-2023.02.04-000001'; + const expectedCount = mockStatsYellowIndex[indexName].primaries?.docs?.count; + + expect( + getDocsCount({ + indexName, + stats: mockStatsYellowIndex, + }) + ).toEqual(expectedCount); + }); + + test('it returns zero when `stats` does NOT contain the `indexName`', () => { + const indexName = 'not-gonna-find-it'; + + expect( + getDocsCount({ + indexName, + stats: mockStatsYellowIndex, + }) + ).toEqual(0); + }); - expect(getIncompatibleStatColor(incompatible)).toBeUndefined(); + test('it returns zero when `stats` is null', () => { + const indexName = '.ds-packetbeat-8.6.1-2023.02.04-000001'; + + expect( + getDocsCount({ + indexName, + stats: null, + }) + ).toEqual(0); + }); + + test('it returns the expected total for a green index, where `primaries.docs.count` and `total.docs.count` have different values', () => { + const indexName = 'auditbeat-custom-index-1'; + + expect( + getDocsCount({ + indexName, + stats: mockStatsGreenIndex, + }) + ).toEqual(mockStatsGreenIndex[indexName].primaries?.docs?.count); + }); }); - test('it returns undefined when incompatible is undefined', () => { - const incompatible = undefined; + describe('getTotalDocsCount', () => { + test('it returns the expected total given a subset of index names in the stats', () => { + const indexName = '.ds-packetbeat-8.5.3-2023.02.04-000001'; + const expectedCount = mockStatsYellowIndex[indexName].primaries?.docs?.count; + + expect( + getTotalDocsCount({ + indexNames: [indexName], + stats: mockStatsYellowIndex, + }) + ).toEqual(expectedCount); + }); + + test('it returns the expected total given all index names in the stats', () => { + const allIndexNamesInStats = [ + '.ds-packetbeat-8.6.1-2023.02.04-000001', + '.ds-packetbeat-8.5.3-2023.02.04-000001', + ]; + + expect( + getTotalDocsCount({ + indexNames: allIndexNamesInStats, + stats: mockStatsYellowIndex, + }) + ).toEqual(3258632); + }); + + test('it returns zero given an empty collection of index names', () => { + expect( + getTotalDocsCount({ + indexNames: [], // <-- empty + stats: mockStatsYellowIndex, + }) + ).toEqual(0); + }); + + test('it returns the expected total for a green index', () => { + const indexName = 'auditbeat-custom-index-1'; + const expectedCount = mockStatsGreenIndex[indexName].primaries?.docs?.count; + + expect( + getTotalDocsCount({ + indexNames: [indexName], + stats: mockStatsGreenIndex, + }) + ).toEqual(expectedCount); + }); + }); + + describe('getIncompatibleStatColor', () => { + test('it returns the expected color when incompatible is greater than zero', () => { + const incompatible = 123; + + expect(getIncompatibleStatColor(incompatible)).toBe('#bd271e'); + }); + + test('it returns undefined when incompatible is zero', () => { + const incompatible = 0; + + expect(getIncompatibleStatColor(incompatible)).toBeUndefined(); + }); + + test('it returns undefined when incompatible is undefined', () => { + const incompatible = undefined; - expect(getIncompatibleStatColor(incompatible)).toBeUndefined(); + expect(getIncompatibleStatColor(incompatible)).toBeUndefined(); + }); }); }); diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.ts b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.ts index ac1fead3d187b..c3574844ae01c 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.ts +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/helpers.ts @@ -71,8 +71,8 @@ const getNextPathWithoutProperties = ({ return key; } - if (shouldReadKeys(value) && key === 'properties') { - return `${pathWithoutProperties}`; // TODO: wrap required? + if (shouldReadKeys(value) && (key === 'properties' || key === 'fields')) { + return `${pathWithoutProperties}`; } else { return `${pathWithoutProperties}.${key}`; } @@ -200,7 +200,7 @@ export const getDocsCount = ({ }: { indexName: string; stats: Record | null; -}): number => (stats && stats[indexName]?.total?.docs?.count) ?? 0; +}): number => (stats && stats[indexName]?.primaries?.docs?.count) ?? 0; export const getTotalDocsCount = ({ indexNames, diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_green_index.ts b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_green_index.ts new file mode 100644 index 0000000000000..74b10123e79f4 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_green_index.ts @@ -0,0 +1,293 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IndicesStatsIndicesStats } from '@elastic/elasticsearch/lib/api/types'; + +/** + * In a deployment where indices have a `green` health status, because there + * are enough nodes to have replicas for all data indices, (i.e. deployments + * created in Elastic Cloud), the `_stats` API returns, for any index, results + * where the index's `primaries.docs.count` and `total.docs.count` have + * **different** values, `4` and `8`, per this mock `_stats` API output + */ +export const mockStatsGreenIndex: Record = { + 'auditbeat-custom-index-1': { + uuid: 'jRlr6H_jSAysOLZ6KynoCQ', + health: 'green', + status: 'open', + primaries: { + docs: { + count: 4, + deleted: 0, + }, + shard_stats: { + total_count: 1, + }, + store: { + size_in_bytes: 28425, + total_data_set_size_in_bytes: 28425, + reserved_in_bytes: 0, + }, + indexing: { + index_total: 4, + index_time_in_millis: 2, + index_current: 0, + index_failed: 0, + delete_total: 0, + delete_time_in_millis: 0, + delete_current: 0, + noop_update_total: 0, + is_throttled: false, + throttle_time_in_millis: 0, + }, + get: { + total: 0, + time_in_millis: 0, + exists_total: 0, + exists_time_in_millis: 0, + missing_total: 0, + missing_time_in_millis: 0, + current: 0, + }, + search: { + open_contexts: 0, + query_total: 2, + query_time_in_millis: 1, + query_current: 0, + fetch_total: 2, + fetch_time_in_millis: 0, + fetch_current: 0, + scroll_total: 0, + scroll_time_in_millis: 0, + scroll_current: 0, + suggest_total: 0, + suggest_time_in_millis: 0, + suggest_current: 0, + }, + merges: { + current: 0, + current_docs: 0, + current_size_in_bytes: 0, + total: 0, + total_time_in_millis: 0, + total_docs: 0, + total_size_in_bytes: 0, + total_stopped_time_in_millis: 0, + total_throttled_time_in_millis: 0, + total_auto_throttle_in_bytes: 20971520, + }, + refresh: { + total: 12, + total_time_in_millis: 29, + external_total: 7, + external_total_time_in_millis: 29, + listeners: 0, + }, + flush: { + total: 1, + periodic: 1, + total_time_in_millis: 4, + }, + warmer: { + current: 0, + total: 6, + total_time_in_millis: 0, + }, + query_cache: { + memory_size_in_bytes: 0, + total_count: 0, + hit_count: 0, + miss_count: 0, + cache_size: 0, + cache_count: 0, + evictions: 0, + }, + fielddata: { + memory_size_in_bytes: 608, + evictions: 0, + }, + completion: { + size_in_bytes: 0, + }, + segments: { + count: 4, + memory_in_bytes: 0, + terms_memory_in_bytes: 0, + stored_fields_memory_in_bytes: 0, + term_vectors_memory_in_bytes: 0, + norms_memory_in_bytes: 0, + points_memory_in_bytes: 0, + doc_values_memory_in_bytes: 0, + index_writer_memory_in_bytes: 0, + version_map_memory_in_bytes: 0, + fixed_bit_set_memory_in_bytes: 0, + max_unsafe_auto_id_timestamp: -1, + file_sizes: {}, + }, + translog: { + operations: 0, + size_in_bytes: 55, + uncommitted_operations: 0, + uncommitted_size_in_bytes: 55, + earliest_last_modified_age: 170944710, + }, + request_cache: { + memory_size_in_bytes: 1792, + evictions: 0, + hit_count: 0, + miss_count: 2, + }, + recovery: { + current_as_source: 0, + current_as_target: 0, + throttle_time_in_millis: 0, + }, + bulk: { + total_operations: 4, + total_time_in_millis: 34, + total_size_in_bytes: 852, + avg_time_in_millis: 2, + avg_size_in_bytes: 73, + }, + }, + total: { + docs: { + count: 8, + deleted: 0, + }, + shard_stats: { + total_count: 2, + }, + store: { + size_in_bytes: 56861, + total_data_set_size_in_bytes: 56861, + reserved_in_bytes: 0, + }, + indexing: { + index_total: 8, + index_time_in_millis: 4, + index_current: 0, + index_failed: 0, + delete_total: 0, + delete_time_in_millis: 0, + delete_current: 0, + noop_update_total: 0, + is_throttled: false, + throttle_time_in_millis: 0, + }, + get: { + total: 0, + time_in_millis: 0, + exists_total: 0, + exists_time_in_millis: 0, + missing_total: 0, + missing_time_in_millis: 0, + current: 0, + }, + search: { + open_contexts: 0, + query_total: 4, + query_time_in_millis: 1, + query_current: 0, + fetch_total: 4, + fetch_time_in_millis: 0, + fetch_current: 0, + scroll_total: 0, + scroll_time_in_millis: 0, + scroll_current: 0, + suggest_total: 0, + suggest_time_in_millis: 0, + suggest_current: 0, + }, + merges: { + current: 0, + current_docs: 0, + current_size_in_bytes: 0, + total: 0, + total_time_in_millis: 0, + total_docs: 0, + total_size_in_bytes: 0, + total_stopped_time_in_millis: 0, + total_throttled_time_in_millis: 0, + total_auto_throttle_in_bytes: 41943040, + }, + refresh: { + total: 21, + total_time_in_millis: 58, + external_total: 14, + external_total_time_in_millis: 59, + listeners: 0, + }, + flush: { + total: 2, + periodic: 2, + total_time_in_millis: 9, + }, + warmer: { + current: 0, + total: 12, + total_time_in_millis: 0, + }, + query_cache: { + memory_size_in_bytes: 1048, + total_count: 0, + hit_count: 0, + miss_count: 0, + cache_size: 0, + cache_count: 0, + evictions: 0, + }, + fielddata: { + memory_size_in_bytes: 608, + evictions: 0, + }, + completion: { + size_in_bytes: 0, + }, + segments: { + count: 8, + memory_in_bytes: 0, + terms_memory_in_bytes: 0, + stored_fields_memory_in_bytes: 0, + term_vectors_memory_in_bytes: 0, + norms_memory_in_bytes: 0, + points_memory_in_bytes: 0, + doc_values_memory_in_bytes: 0, + index_writer_memory_in_bytes: 0, + version_map_memory_in_bytes: 0, + fixed_bit_set_memory_in_bytes: 0, + max_unsafe_auto_id_timestamp: 1676070541751, + file_sizes: {}, + }, + translog: { + operations: 0, + size_in_bytes: 110, + uncommitted_operations: 0, + uncommitted_size_in_bytes: 110, + earliest_last_modified_age: 170944710, + }, + request_cache: { + memory_size_in_bytes: 3760, + evictions: 0, + hit_count: 0, + miss_count: 4, + }, + recovery: { + current_as_source: 0, + current_as_target: 0, + throttle_time_in_millis: 0, + }, + bulk: { + total_operations: 8, + total_time_in_millis: 36, + total_size_in_bytes: 1704, + avg_time_in_millis: 1, + avg_size_in_bytes: 73, + }, + }, + }, +}; diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_yellow_index.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_yellow_index.tsx new file mode 100644 index 0000000000000..49b5b19352185 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/stats/mock_stats_yellow_index.tsx @@ -0,0 +1,568 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IndicesStatsIndicesStats } from '@elastic/elasticsearch/lib/api/types'; + +/** + * In a deployment where indices have a `yellow` health status, the + * [`_stats`](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-stats.html) + * API returns, (for an arbitrary index), results where the index's + * `primaries.docs.count` and `total.docs.count` have the same value, per this + * mock `_stats` API output + */ +export const mockStatsYellowIndex: Record = { + '.ds-packetbeat-8.6.1-2023.02.04-000001': { + uuid: 'x5Uuw4j4QM2YidHLNixCwg', + health: 'yellow', + status: 'open', + primaries: { + docs: { + count: 1628343, + deleted: 0, + }, + shard_stats: { + total_count: 1, + }, + store: { + size_in_bytes: 731583142, + total_data_set_size_in_bytes: 731583142, + reserved_in_bytes: 0, + }, + indexing: { + index_total: 0, + index_time_in_millis: 0, + index_current: 0, + index_failed: 0, + delete_total: 0, + delete_time_in_millis: 0, + delete_current: 0, + noop_update_total: 0, + is_throttled: false, + throttle_time_in_millis: 0, + }, + get: { + total: 0, + time_in_millis: 0, + exists_total: 0, + exists_time_in_millis: 0, + missing_total: 0, + missing_time_in_millis: 0, + current: 0, + }, + search: { + open_contexts: 0, + query_total: 32, + query_time_in_millis: 111, + query_current: 0, + fetch_total: 32, + fetch_time_in_millis: 0, + fetch_current: 0, + scroll_total: 0, + scroll_time_in_millis: 0, + scroll_current: 0, + suggest_total: 0, + suggest_time_in_millis: 0, + suggest_current: 0, + }, + merges: { + current: 0, + current_docs: 0, + current_size_in_bytes: 0, + total: 0, + total_time_in_millis: 0, + total_docs: 0, + total_size_in_bytes: 0, + total_stopped_time_in_millis: 0, + total_throttled_time_in_millis: 0, + total_auto_throttle_in_bytes: 20971520, + }, + refresh: { + total: 2, + total_time_in_millis: 0, + external_total: 2, + external_total_time_in_millis: 15, + listeners: 0, + }, + flush: { + total: 1, + periodic: 1, + total_time_in_millis: 0, + }, + warmer: { + current: 0, + total: 1, + total_time_in_millis: 15, + }, + query_cache: { + memory_size_in_bytes: 0, + total_count: 301, + hit_count: 0, + miss_count: 301, + cache_size: 0, + cache_count: 0, + evictions: 0, + }, + fielddata: { + memory_size_in_bytes: 1080, + evictions: 0, + }, + completion: { + size_in_bytes: 0, + }, + segments: { + count: 19, + memory_in_bytes: 0, + terms_memory_in_bytes: 0, + stored_fields_memory_in_bytes: 0, + term_vectors_memory_in_bytes: 0, + norms_memory_in_bytes: 0, + points_memory_in_bytes: 0, + doc_values_memory_in_bytes: 0, + index_writer_memory_in_bytes: 0, + version_map_memory_in_bytes: 0, + fixed_bit_set_memory_in_bytes: 304, + max_unsafe_auto_id_timestamp: -1, + file_sizes: {}, + }, + translog: { + operations: 0, + size_in_bytes: 55, + uncommitted_operations: 0, + uncommitted_size_in_bytes: 55, + earliest_last_modified_age: 136482466, + }, + request_cache: { + memory_size_in_bytes: 3680, + evictions: 0, + hit_count: 28, + miss_count: 4, + }, + recovery: { + current_as_source: 0, + current_as_target: 0, + throttle_time_in_millis: 0, + }, + bulk: { + total_operations: 0, + total_time_in_millis: 0, + total_size_in_bytes: 0, + avg_time_in_millis: 0, + avg_size_in_bytes: 0, + }, + }, + total: { + docs: { + count: 1628343, + deleted: 0, + }, + shard_stats: { + total_count: 1, + }, + store: { + size_in_bytes: 731583142, + total_data_set_size_in_bytes: 731583142, + reserved_in_bytes: 0, + }, + indexing: { + index_total: 0, + index_time_in_millis: 0, + index_current: 0, + index_failed: 0, + delete_total: 0, + delete_time_in_millis: 0, + delete_current: 0, + noop_update_total: 0, + is_throttled: false, + throttle_time_in_millis: 0, + }, + get: { + total: 0, + time_in_millis: 0, + exists_total: 0, + exists_time_in_millis: 0, + missing_total: 0, + missing_time_in_millis: 0, + current: 0, + }, + search: { + open_contexts: 0, + query_total: 32, + query_time_in_millis: 111, + query_current: 0, + fetch_total: 32, + fetch_time_in_millis: 0, + fetch_current: 0, + scroll_total: 0, + scroll_time_in_millis: 0, + scroll_current: 0, + suggest_total: 0, + suggest_time_in_millis: 0, + suggest_current: 0, + }, + merges: { + current: 0, + current_docs: 0, + current_size_in_bytes: 0, + total: 0, + total_time_in_millis: 0, + total_docs: 0, + total_size_in_bytes: 0, + total_stopped_time_in_millis: 0, + total_throttled_time_in_millis: 0, + total_auto_throttle_in_bytes: 20971520, + }, + refresh: { + total: 2, + total_time_in_millis: 0, + external_total: 2, + external_total_time_in_millis: 15, + listeners: 0, + }, + flush: { + total: 1, + periodic: 1, + total_time_in_millis: 0, + }, + warmer: { + current: 0, + total: 1, + total_time_in_millis: 15, + }, + query_cache: { + memory_size_in_bytes: 0, + total_count: 301, + hit_count: 0, + miss_count: 301, + cache_size: 0, + cache_count: 0, + evictions: 0, + }, + fielddata: { + memory_size_in_bytes: 1080, + evictions: 0, + }, + completion: { + size_in_bytes: 0, + }, + segments: { + count: 19, + memory_in_bytes: 0, + terms_memory_in_bytes: 0, + stored_fields_memory_in_bytes: 0, + term_vectors_memory_in_bytes: 0, + norms_memory_in_bytes: 0, + points_memory_in_bytes: 0, + doc_values_memory_in_bytes: 0, + index_writer_memory_in_bytes: 0, + version_map_memory_in_bytes: 0, + fixed_bit_set_memory_in_bytes: 304, + max_unsafe_auto_id_timestamp: -1, + file_sizes: {}, + }, + translog: { + operations: 0, + size_in_bytes: 55, + uncommitted_operations: 0, + uncommitted_size_in_bytes: 55, + earliest_last_modified_age: 136482466, + }, + request_cache: { + memory_size_in_bytes: 3680, + evictions: 0, + hit_count: 28, + miss_count: 4, + }, + recovery: { + current_as_source: 0, + current_as_target: 0, + throttle_time_in_millis: 0, + }, + bulk: { + total_operations: 0, + total_time_in_millis: 0, + total_size_in_bytes: 0, + avg_time_in_millis: 0, + avg_size_in_bytes: 0, + }, + }, + }, + '.ds-packetbeat-8.5.3-2023.02.04-000001': { + uuid: 'we0vNWm2Q6iz6uHubyHS6Q', + health: 'yellow', + status: 'open', + primaries: { + docs: { + count: 1630289, + deleted: 0, + }, + shard_stats: { + total_count: 1, + }, + store: { + size_in_bytes: 733175040, + total_data_set_size_in_bytes: 733175040, + reserved_in_bytes: 0, + }, + indexing: { + index_total: 0, + index_time_in_millis: 0, + index_current: 0, + index_failed: 0, + delete_total: 0, + delete_time_in_millis: 0, + delete_current: 0, + noop_update_total: 0, + is_throttled: false, + throttle_time_in_millis: 0, + }, + get: { + total: 0, + time_in_millis: 0, + exists_total: 0, + exists_time_in_millis: 0, + missing_total: 0, + missing_time_in_millis: 0, + current: 0, + }, + search: { + open_contexts: 0, + query_total: 32, + query_time_in_millis: 111, + query_current: 0, + fetch_total: 32, + fetch_time_in_millis: 0, + fetch_current: 0, + scroll_total: 0, + scroll_time_in_millis: 0, + scroll_current: 0, + suggest_total: 0, + suggest_time_in_millis: 0, + suggest_current: 0, + }, + merges: { + current: 0, + current_docs: 0, + current_size_in_bytes: 0, + total: 0, + total_time_in_millis: 0, + total_docs: 0, + total_size_in_bytes: 0, + total_stopped_time_in_millis: 0, + total_throttled_time_in_millis: 0, + total_auto_throttle_in_bytes: 20971520, + }, + refresh: { + total: 2, + total_time_in_millis: 0, + external_total: 2, + external_total_time_in_millis: 2, + listeners: 0, + }, + flush: { + total: 1, + periodic: 1, + total_time_in_millis: 0, + }, + warmer: { + current: 0, + total: 1, + total_time_in_millis: 2, + }, + query_cache: { + memory_size_in_bytes: 0, + total_count: 203, + hit_count: 0, + miss_count: 203, + cache_size: 0, + cache_count: 0, + evictions: 0, + }, + fielddata: { + memory_size_in_bytes: 1168, + evictions: 0, + }, + completion: { + size_in_bytes: 0, + }, + segments: { + count: 20, + memory_in_bytes: 0, + terms_memory_in_bytes: 0, + stored_fields_memory_in_bytes: 0, + term_vectors_memory_in_bytes: 0, + norms_memory_in_bytes: 0, + points_memory_in_bytes: 0, + doc_values_memory_in_bytes: 0, + index_writer_memory_in_bytes: 0, + version_map_memory_in_bytes: 0, + fixed_bit_set_memory_in_bytes: 320, + max_unsafe_auto_id_timestamp: -1, + file_sizes: {}, + }, + translog: { + operations: 0, + size_in_bytes: 55, + uncommitted_operations: 0, + uncommitted_size_in_bytes: 55, + earliest_last_modified_age: 136482425, + }, + request_cache: { + memory_size_in_bytes: 3688, + evictions: 0, + hit_count: 28, + miss_count: 4, + }, + recovery: { + current_as_source: 0, + current_as_target: 0, + throttle_time_in_millis: 0, + }, + bulk: { + total_operations: 0, + total_time_in_millis: 0, + total_size_in_bytes: 0, + avg_time_in_millis: 0, + avg_size_in_bytes: 0, + }, + }, + total: { + docs: { + count: 1630289, + deleted: 0, + }, + shard_stats: { + total_count: 1, + }, + store: { + size_in_bytes: 733175040, + total_data_set_size_in_bytes: 733175040, + reserved_in_bytes: 0, + }, + indexing: { + index_total: 0, + index_time_in_millis: 0, + index_current: 0, + index_failed: 0, + delete_total: 0, + delete_time_in_millis: 0, + delete_current: 0, + noop_update_total: 0, + is_throttled: false, + throttle_time_in_millis: 0, + }, + get: { + total: 0, + time_in_millis: 0, + exists_total: 0, + exists_time_in_millis: 0, + missing_total: 0, + missing_time_in_millis: 0, + current: 0, + }, + search: { + open_contexts: 0, + query_total: 32, + query_time_in_millis: 111, + query_current: 0, + fetch_total: 32, + fetch_time_in_millis: 0, + fetch_current: 0, + scroll_total: 0, + scroll_time_in_millis: 0, + scroll_current: 0, + suggest_total: 0, + suggest_time_in_millis: 0, + suggest_current: 0, + }, + merges: { + current: 0, + current_docs: 0, + current_size_in_bytes: 0, + total: 0, + total_time_in_millis: 0, + total_docs: 0, + total_size_in_bytes: 0, + total_stopped_time_in_millis: 0, + total_throttled_time_in_millis: 0, + total_auto_throttle_in_bytes: 20971520, + }, + refresh: { + total: 2, + total_time_in_millis: 0, + external_total: 2, + external_total_time_in_millis: 2, + listeners: 0, + }, + flush: { + total: 1, + periodic: 1, + total_time_in_millis: 0, + }, + warmer: { + current: 0, + total: 1, + total_time_in_millis: 2, + }, + query_cache: { + memory_size_in_bytes: 0, + total_count: 203, + hit_count: 0, + miss_count: 203, + cache_size: 0, + cache_count: 0, + evictions: 0, + }, + fielddata: { + memory_size_in_bytes: 1168, + evictions: 0, + }, + completion: { + size_in_bytes: 0, + }, + segments: { + count: 20, + memory_in_bytes: 0, + terms_memory_in_bytes: 0, + stored_fields_memory_in_bytes: 0, + term_vectors_memory_in_bytes: 0, + norms_memory_in_bytes: 0, + points_memory_in_bytes: 0, + doc_values_memory_in_bytes: 0, + index_writer_memory_in_bytes: 0, + version_map_memory_in_bytes: 0, + fixed_bit_set_memory_in_bytes: 320, + max_unsafe_auto_id_timestamp: -1, + file_sizes: {}, + }, + translog: { + operations: 0, + size_in_bytes: 55, + uncommitted_operations: 0, + uncommitted_size_in_bytes: 55, + earliest_last_modified_age: 136482425, + }, + request_cache: { + memory_size_in_bytes: 3688, + evictions: 0, + hit_count: 28, + miss_count: 4, + }, + recovery: { + current_as_source: 0, + current_as_target: 0, + throttle_time_in_millis: 0, + }, + bulk: { + total_operations: 0, + total_time_in_millis: 0, + total_size_in_bytes: 0, + avg_time_in_millis: 0, + avg_size_in_bytes: 0, + }, + }, + }, +}; diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/test_providers/index.tsx b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/test_providers/index.tsx new file mode 100644 index 0000000000000..984e38cd0de59 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/impl/data_quality/mock/test_providers/index.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { I18nProvider } from '@kbn/i18n-react'; +import { euiDarkVars } from '@kbn/ui-theme'; +import React from 'react'; +import { ThemeProvider } from 'styled-components'; + +interface Props { + children: React.ReactNode; +} + +window.scrollTo = jest.fn(); + +/** A utility for wrapping children in the providers required to run tests */ +export const TestProvidersComponent: React.FC = ({ children }) => ( + + ({ eui: euiDarkVars, darkMode: true })}>{children} + +); + +TestProvidersComponent.displayName = 'TestProvidersComponent'; + +export const TestProviders = React.memo(TestProvidersComponent); diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/jest.config.js b/x-pack/packages/kbn-ecs-data-quality-dashboard/jest.config.js index 5f6465bb21a52..cd5c74e9b44bc 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/jest.config.js +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/jest.config.js @@ -9,4 +9,5 @@ module.exports = { preset: '@kbn/test', rootDir: '../../..', roots: ['/x-pack/packages/kbn-ecs-data-quality-dashboard'], + setupFilesAfterEnv: ['/x-pack/packages/kbn-ecs-data-quality-dashboard/setup_tests.ts'], }; diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/setup_tests.ts b/x-pack/packages/kbn-ecs-data-quality-dashboard/setup_tests.ts new file mode 100644 index 0000000000000..72e0edd0d07f7 --- /dev/null +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/setup_tests.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. + */ + +// eslint-disable-next-line import/no-extraneous-dependencies +import '@testing-library/jest-dom'; diff --git a/x-pack/packages/kbn-ecs-data-quality-dashboard/tsconfig.json b/x-pack/packages/kbn-ecs-data-quality-dashboard/tsconfig.json index ddb539c293a2b..09b55094f3b23 100644 --- a/x-pack/packages/kbn-ecs-data-quality-dashboard/tsconfig.json +++ b/x-pack/packages/kbn-ecs-data-quality-dashboard/tsconfig.json @@ -18,6 +18,7 @@ "kbn_references": [ "@kbn/ecs", "@kbn/i18n", + "@kbn/i18n-react", "@kbn/ui-theme", ] } From 96d10f05b325cb2a621b24194f5ebabab578e793 Mon Sep 17 00:00:00 2001 From: Alexi Doak <109488926+doakalexi@users.noreply.github.com> Date: Tue, 14 Feb 2023 08:44:43 -0500 Subject: [PATCH 174/203] [Response Ops][Alerting] Editing rule action does not auto-populate default summary message (#151048) Resolves https://github.com/elastic/kibana/issues/150715 ## Summary When editing an existing action on an existing rule, switching between the For each alert and Summary alert dropdown does switch the existing action message to the default message. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### To verify - create a rule with an action that uses `For each alert` notification frequency; use the default message - edit your new rule and switch the action frequency to `Summary of alerts`; notice that the message does change to the default summary message - create a rule with an action that uses `Summary of alerts` notification frequency; use the default message - edit your new rule and switch the action frequency to `For each alert`; notice that the message does change to the default summary message - repeat the steps above and but create the rule a with an action that does not use the default message --- .../email/email_params.test.tsx | 58 +++++++++++++++++++ .../connector_types/email/email_params.tsx | 2 + .../server_log/server_log_params.test.tsx | 52 +++++++++++++++++ .../server_log/server_log_params.tsx | 11 +++- .../slack/slack_params.test.tsx | 52 +++++++++++++++++ .../connector_types/slack/slack_params.tsx | 2 + .../teams/teams_params.test.tsx | 52 +++++++++++++++++ .../connector_types/teams/teams_params.tsx | 5 +- .../action_type_form.tsx | 4 ++ .../triggers_actions_ui/public/types.ts | 1 + 10 files changed, 236 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.test.tsx index 1762fc0b39f8e..7626606a0bf60 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.test.tsx @@ -128,4 +128,62 @@ describe('EmailParamsFields renders', () => { expect(editAction).not.toHaveBeenCalledWith('message', 'Some different default message', 0); }); + + test('when useDefaultMessage is set to true and the default message changes, the underlying message is replaced with the default message', () => { + const actionParams = { + cc: [], + bcc: [], + to: ['test@test.com'], + subject: 'test', + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: true, + defaultMessage: 'Some different default message', + }); + + expect(editAction).toHaveBeenCalledWith('message', 'Some different default message', 0); + }); + + test('when useDefaultMessage is set to false and the default message changes, the underlying message is not changed', () => { + const actionParams = { + cc: [], + bcc: [], + to: ['test@test.com'], + subject: 'test', + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: false, + defaultMessage: 'Some different default message', + }); + + expect(editAction).not.toHaveBeenCalled(); + }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx index 29e2a8525ae04..a8df45ba0e33f 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/email/email_params.tsx @@ -29,6 +29,7 @@ export const EmailParamsFields = ({ isDisabled, onBlur = noop, showEmailSubjectAndMessage = true, + useDefaultMessage, }: ActionParamsProps) => { const { to, cc, bcc, subject, message } = actionParams; const toOptions = to ? to.map((label: string) => ({ label })) : []; @@ -42,6 +43,7 @@ export const EmailParamsFields = ({ >([false, defaultMessage]); useEffect(() => { if ( + useDefaultMessage || !actionParams?.message || (isUsingDefault && actionParams?.message === defaultMessageUsed && diff --git a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.test.tsx index 90bed8f28701a..6a5426d952897 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.test.tsx @@ -136,4 +136,56 @@ describe('ServerLogParamsFields renders', () => { expect(editAction).not.toHaveBeenCalledWith('message', 'Some different default message', 0); }); + + test('when useDefaultMessage is set to true and the default message changes, the underlying message is replaced with the default message', () => { + const actionParams = { + level: ServerLogLevelOptions.TRACE, + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: true, + defaultMessage: 'Some different default message', + }); + + expect(editAction).toHaveBeenCalledWith('message', 'Some different default message', 0); + }); + + test('when useDefaultMessage is set to false and the default message changes, the underlying message is not changed', () => { + const actionParams = { + level: ServerLogLevelOptions.TRACE, + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: false, + defaultMessage: 'Some different default message', + }); + + expect(editAction).not.toHaveBeenCalled(); + }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx index f9882f1a67c76..7c74245289833 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log_params.tsx @@ -14,7 +14,15 @@ import { ServerLogActionParams } from '../types'; export const ServerLogParamsFields: React.FunctionComponent< ActionParamsProps -> = ({ actionParams, editAction, index, errors, messageVariables, defaultMessage }) => { +> = ({ + actionParams, + editAction, + index, + errors, + messageVariables, + defaultMessage, + useDefaultMessage, +}) => { const { message, level } = actionParams; const levelOptions = [ { value: 'trace', text: 'Trace' }, @@ -36,6 +44,7 @@ export const ServerLogParamsFields: React.FunctionComponent< >([false, defaultMessage]); useEffect(() => { if ( + useDefaultMessage || !actionParams?.message || (isUsingDefault && actionParams?.message === defaultMessageUsed && diff --git a/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.test.tsx index 6611b33e094b2..faf6dc208a116 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.test.tsx @@ -28,4 +28,56 @@ describe('SlackParamsFields renders', () => { 'test message' ); }); + + test('when useDefaultMessage is set to true and the default message changes, the underlying message is replaced with the default message', () => { + const actionParams = { + message: 'not the default message', + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: true, + defaultMessage: 'Some different default message', + }); + + expect(editAction).toHaveBeenCalledWith('message', 'Some different default message', 0); + }); + + test('when useDefaultMessage is set to false and the default message changes, the underlying message is not changed', () => { + const actionParams = { + message: 'not the default message', + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: false, + defaultMessage: 'Some different default message', + }); + + expect(editAction).not.toHaveBeenCalled(); + }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.tsx index ec62b64b47961..4d219aebfe5bd 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/slack/slack_params.tsx @@ -18,6 +18,7 @@ const SlackParamsFields: React.FunctionComponent { const { message } = actionParams; const [[isUsingDefault, defaultMessageUsed], setDefaultMessageUsage] = useState< @@ -25,6 +26,7 @@ const SlackParamsFields: React.FunctionComponent([false, defaultMessage]); useEffect(() => { if ( + useDefaultMessage || !actionParams?.message || (isUsingDefault && actionParams?.message === defaultMessageUsed && diff --git a/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.test.tsx index ac1228ac5fda4..b730e21bb350a 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.test.tsx @@ -29,4 +29,56 @@ describe('TeamsParamsFields renders', () => { 'test message' ); }); + + test('when useDefaultMessage is set to true and the default message changes, the underlying message is replaced with the default message', () => { + const actionParams = { + message: 'not the default message', + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: true, + defaultMessage: 'Some different default message', + }); + + expect(editAction).toHaveBeenCalledWith('message', 'Some different default message', 0); + }); + + test('when useDefaultMessage is set to false and the default message changes, the underlying message is not changed', () => { + const actionParams = { + message: 'not the default message', + }; + + const editAction = jest.fn(); + const wrapper = mountWithIntl( + + ); + const text = wrapper.find('[data-test-subj="messageTextArea"]').first().text(); + expect(text).toEqual('not the default message'); + + wrapper.setProps({ + useDefaultMessage: false, + defaultMessage: 'Some different default message', + }); + + expect(editAction).not.toHaveBeenCalled(); + }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.tsx index d2ef099bee82b..93f8d0e0fe02e 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/teams/teams_params.tsx @@ -18,14 +18,15 @@ const TeamsParamsFields: React.FunctionComponent { const { message } = actionParams; useEffect(() => { - if (!message && defaultMessage && defaultMessage.length > 0) { + if (useDefaultMessage || (!message && defaultMessage && defaultMessage.length > 0)) { editAction('message', defaultMessage, index); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [defaultMessage]); return ( { @@ -264,6 +265,8 @@ export const ActionTypeForm = ({ )} onSummaryChange={useCallback( (summary: boolean) => { + // use the default message when a user toggles between action frequencies + setUseDefaultMessage(true); setActionFrequencyProperty('summary', summary, index); }, [setActionFrequencyProperty, index] @@ -387,6 +390,7 @@ export const ActionTypeForm = ({ ? defaultSummaryMessage : selectedActionGroup?.defaultActionMessage ?? defaultActionMessage } + useDefaultMessage={useDefaultMessage} actionConnector={actionConnector} executionMode={ActionConnectorMode.ActionForm} /> diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index 6622b35fa8920..f99573150faaf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -207,6 +207,7 @@ export interface ActionParamsProps { errors: IErrorObject; messageVariables?: ActionVariable[]; defaultMessage?: string; + useDefaultMessage?: boolean; actionConnector?: ActionConnector; isLoading?: boolean; isDisabled?: boolean; From fe78c05e1f493ffa2d995da37c8cc88fb1457c4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Tue, 14 Feb 2023 14:49:24 +0100 Subject: [PATCH 175/203] [Osquery] Cleanup spaces dependency (#151059) ## Summary Cleanup unused `spaces` plugin dependency --- x-pack/plugins/osquery/public/types.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugins/osquery/public/types.ts b/x-pack/plugins/osquery/public/types.ts index f6d05a3d45996..6f26c56fcf91b 100644 --- a/x-pack/plugins/osquery/public/types.ts +++ b/x-pack/plugins/osquery/public/types.ts @@ -18,7 +18,6 @@ import type { } from '@kbn/triggers-actions-ui-plugin/public'; import type { CasesUiStart, CasesUiSetup } from '@kbn/cases-plugin/public'; import type { TimelinesUIStart } from '@kbn/timelines-plugin/public'; -import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { getLazyOsqueryResults, getLazyLiveQueryField, @@ -50,7 +49,6 @@ export interface StartPlugins { fleet: FleetStart; lens?: LensPublicStart; security: SecurityPluginStart; - spaces: SpacesPluginStart; triggersActionsUi: TriggersAndActionsUIPublicPluginStart; cases: CasesUiStart; timelines: TimelinesUIStart; From 687294d4d30e936aa95b4a4c566b29c4462ab362 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 14 Feb 2023 14:05:34 +0000 Subject: [PATCH 176/203] [Fleet] Bugfix: prevent status runtime query going over character limit (#150910) ## Summary Closes #150577 if there are too many agent policies in a system, we were creating too big a runtime query for elastic and the query would be rejected. This PR adds a limit, if the user has more than 750 agent policies then agents will not be marked as inactive anymore. If the user reaches the limit then a warning badge is displayed (the text underlined has also been added): Screenshot 2023-02-13 at 20 14 31 Integration test added. --- .../test_suites/core_plugins/rendering.ts | 1 + x-pack/plugins/fleet/common/types/index.ts | 1 + .../agent_policy_advanced_fields/index.tsx | 41 ++- x-pack/plugins/fleet/server/config.ts | 4 + .../agents/build_status_runtime_field.test.ts | 259 +++--------------- .../agents/build_status_runtime_field.ts | 125 +++++++-- .../services/agents/update_agent_tags.test.ts | 9 +- .../apis/agents/status.ts | 49 ++++ x-pack/test/fleet_api_integration/config.ts | 1 + 9 files changed, 239 insertions(+), 251 deletions(-) diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 3a15129dcd2d6..19ee7178fcd94 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -190,6 +190,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.discoverEnhanced.actions.exploreDataInContextMenu.enabled (boolean)', 'xpack.fleet.agents.enabled (boolean)', 'xpack.fleet.enableExperimental (array)', + 'xpack.fleet.developer.maxAgentPoliciesWithInactivityTimeout (number)', 'xpack.global_search.search_timeout (duration)', 'xpack.graph.canEditDrillDownUrls (boolean)', 'xpack.graph.savePolicy (alternatives)', diff --git a/x-pack/plugins/fleet/common/types/index.ts b/x-pack/plugins/fleet/common/types/index.ts index 202dd0c81ead5..d3a7f9ee95bd1 100644 --- a/x-pack/plugins/fleet/common/types/index.ts +++ b/x-pack/plugins/fleet/common/types/index.ts @@ -40,6 +40,7 @@ export interface FleetConfigType { agentPolicySchemaUpgradeBatchSize?: number; }; developer?: { + maxAgentPoliciesWithInactivityTimeout?: number; disableRegistryVersionCheck?: boolean; bundledPackageLocation?: string; }; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx index 9dbc1754fd12d..cf3d6e84137e8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/index.tsx @@ -24,13 +24,14 @@ import { EuiFlexGroup, EuiFlexItem, EuiBetaBadge, + EuiBadge, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { dataTypes } from '../../../../../../../common/constants'; +import { AGENT_POLICY_SAVED_OBJECT_TYPE, dataTypes } from '../../../../../../../common/constants'; import type { NewAgentPolicy, AgentPolicy } from '../../../../types'; -import { useStartServices } from '../../../../hooks'; +import { useStartServices, useConfig, useGetAgentPolicies } from '../../../../hooks'; import { AgentPolicyPackageBadge } from '../../../../components'; @@ -63,12 +64,26 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent = }) => { const { agentFqdnMode: agentFqdnModeEnabled } = ExperimentalFeaturesService.get(); const { docLinks } = useStartServices(); + const config = useConfig(); + const maxAgentPoliciesWithInactivityTimeout = + config.developer?.maxAgentPoliciesWithInactivityTimeout ?? 0; const [touchedFields, setTouchedFields] = useState<{ [key: string]: boolean }>({}); const { dataOutputOptions, monitoringOutputOptions, isLoading: isLoadingOptions, } = useOutputOptions(agentPolicy); + + const { data: agentPoliciesData } = useGetAgentPolicies({ + page: 1, + perPage: 0, + kuery: `${AGENT_POLICY_SAVED_OBJECT_TYPE}.inactivity_timeout:*`, + }); + + const totalAgentPoliciesWithInactivityTimeout = agentPoliciesData?.total ?? 0; + const tooManyAgentPoliciesForInactivityTimeout = + maxAgentPoliciesWithInactivityTimeout !== undefined && + totalAgentPoliciesWithInactivityTimeout > (maxAgentPoliciesWithInactivityTimeout ?? 0); const { dataDownloadSourceOptions, isLoading: isLoadingDownloadSources } = useDownloadSourcesOptions(agentPolicy); @@ -273,12 +288,32 @@ export const AgentPolicyAdvancedOptionsContent: React.FunctionComponent = id="xpack.fleet.agentPolicyForm.inactivityTimeoutLabel" defaultMessage="Inactivity timeout" /> + {tooManyAgentPoliciesForInactivityTimeout && ( + <> +   + + } + > + + + + + + )}

    } description={ } > diff --git a/x-pack/plugins/fleet/server/config.ts b/x-pack/plugins/fleet/server/config.ts index 6cbbbd3a94bfe..d5312bf9bc65c 100644 --- a/x-pack/plugins/fleet/server/config.ts +++ b/x-pack/plugins/fleet/server/config.ts @@ -35,6 +35,9 @@ export const config: PluginConfigDescriptor = { enabled: true, }, enableExperimental: true, + developer: { + maxAgentPoliciesWithInactivityTimeout: true, + }, }, deprecations: ({ renameFromRoot, unused, unusedFromRoot }) => [ // Unused settings before Fleet server exists @@ -126,6 +129,7 @@ export const config: PluginConfigDescriptor = { }) ), developer: schema.object({ + maxAgentPoliciesWithInactivityTimeout: schema.maybe(schema.number()), disableRegistryVersionCheck: schema.boolean({ defaultValue: false }), allowAgentUpgradeSourceUri: schema.boolean({ defaultValue: false }), bundledPackageLocation: schema.string({ defaultValue: DEFAULT_BUNDLED_PACKAGE_LOCATION }), diff --git a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts index 249b74db13256..2c54d7d50c57c 100644 --- a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.test.ts @@ -15,54 +15,13 @@ describe('buildStatusRuntimeField', () => { }); it('should build the correct runtime field if there are no inactivity timeouts', () => { const inactivityTimeouts: InactivityTimeouts = []; - const runtimeField = _buildStatusRuntimeField(inactivityTimeouts); + const runtimeField = _buildStatusRuntimeField({ inactivityTimeouts }); expect(runtimeField).toMatchInlineSnapshot(` Object { "status": Object { "script": Object { "lang": "painless", - "source": " - long lastCheckinMillis = doc['last_checkin'].size() > 0 - ? doc['last_checkin'].value.toInstant().toEpochMilli() - : ( - doc['enrolled_at'].size() > 0 - ? doc['enrolled_at'].value.toInstant().toEpochMilli() - : -1 - ); - if (doc['active'].size() > 0 && doc['active'].value == false) { - emit('unenrolled'); - } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && false) { - emit('inactive'); - } else if ( - lastCheckinMillis > 0 - && lastCheckinMillis - < (1234567590123L) - ) { - emit('offline'); - } else if ( - doc['policy_revision_idx'].size() == 0 || ( - doc['upgrade_started_at'].size() > 0 && - doc['upgraded_at'].size() == 0 - ) - ) { - emit('updating'); - } else if (doc['last_checkin'].size() == 0) { - emit('enrolling'); - } else if (doc['unenrollment_started_at'].size() > 0) { - emit('unenrolling'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'error' - ) { - emit('error'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'degraded' - ) { - emit('degraded'); - } else { - emit('online'); - }", + "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() : ( doc['enrolled_at'].size() > 0 ? doc['enrolled_at'].value.toInstant().toEpochMilli() : -1 ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if ( lastCheckinMillis > 0 && lastCheckinMillis < 1234567590123L ) { emit('offline'); } else if ( doc['policy_revision_idx'].size() == 0 || ( doc['upgrade_started_at'].size() > 0 && doc['upgraded_at'].size() == 0 ) ) { emit('updating'); } else if (doc['last_checkin'].size() == 0) { emit('enrolling'); } else if (doc['unenrollment_started_at'].size() > 0) { emit('unenrolling'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'error' ) { emit('error'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'degraded' ) { emit('degraded'); } else { emit('online'); }", }, "type": "keyword", }, @@ -71,54 +30,13 @@ describe('buildStatusRuntimeField', () => { }); it('should build the correct runtime field if there are no inactivity timeouts (prefix)', () => { const inactivityTimeouts: InactivityTimeouts = []; - const runtimeField = _buildStatusRuntimeField(inactivityTimeouts, 'my.prefix.'); + const runtimeField = _buildStatusRuntimeField({ inactivityTimeouts, pathPrefix: 'my.prefix.' }); expect(runtimeField).toMatchInlineSnapshot(` Object { "status": Object { "script": Object { "lang": "painless", - "source": " - long lastCheckinMillis = doc['my.prefix.last_checkin'].size() > 0 - ? doc['my.prefix.last_checkin'].value.toInstant().toEpochMilli() - : ( - doc['my.prefix.enrolled_at'].size() > 0 - ? doc['my.prefix.enrolled_at'].value.toInstant().toEpochMilli() - : -1 - ); - if (doc['my.prefix.active'].size() > 0 && doc['my.prefix.active'].value == false) { - emit('unenrolled'); - } else if (lastCheckinMillis > 0 && doc['my.prefix.policy_id'].size() > 0 && false) { - emit('inactive'); - } else if ( - lastCheckinMillis > 0 - && lastCheckinMillis - < (1234567590123L) - ) { - emit('offline'); - } else if ( - doc['my.prefix.policy_revision_idx'].size() == 0 || ( - doc['my.prefix.upgrade_started_at'].size() > 0 && - doc['my.prefix.upgraded_at'].size() == 0 - ) - ) { - emit('updating'); - } else if (doc['my.prefix.last_checkin'].size() == 0) { - emit('enrolling'); - } else if (doc['my.prefix.unenrollment_started_at'].size() > 0) { - emit('unenrolling'); - } else if ( - doc['my.prefix.last_checkin_status'].size() > 0 && - doc['my.prefix.last_checkin_status'].value.toLowerCase() == 'error' - ) { - emit('error'); - } else if ( - doc['my.prefix.last_checkin_status'].size() > 0 && - doc['my.prefix.last_checkin_status'].value.toLowerCase() == 'degraded' - ) { - emit('degraded'); - } else { - emit('online'); - }", + "source": " long lastCheckinMillis = doc['my.prefix.last_checkin'].size() > 0 ? doc['my.prefix.last_checkin'].value.toInstant().toEpochMilli() : ( doc['my.prefix.enrolled_at'].size() > 0 ? doc['my.prefix.enrolled_at'].value.toInstant().toEpochMilli() : -1 ); if (doc['my.prefix.active'].size() > 0 && doc['my.prefix.active'].value == false) { emit('unenrolled'); } else if ( lastCheckinMillis > 0 && lastCheckinMillis < 1234567590123L ) { emit('offline'); } else if ( doc['my.prefix.policy_revision_idx'].size() == 0 || ( doc['my.prefix.upgrade_started_at'].size() > 0 && doc['my.prefix.upgraded_at'].size() == 0 ) ) { emit('updating'); } else if (doc['my.prefix.last_checkin'].size() == 0) { emit('enrolling'); } else if (doc['my.prefix.unenrollment_started_at'].size() > 0) { emit('unenrolling'); } else if ( doc['my.prefix.last_checkin_status'].size() > 0 && doc['my.prefix.last_checkin_status'].value.toLowerCase() == 'error' ) { emit('error'); } else if ( doc['my.prefix.last_checkin_status'].size() > 0 && doc['my.prefix.last_checkin_status'].value.toLowerCase() == 'degraded' ) { emit('degraded'); } else { emit('online'); }", }, "type": "keyword", }, @@ -132,54 +50,13 @@ describe('buildStatusRuntimeField', () => { policyIds: ['policy-1'], }, ]; - const runtimeField = _buildStatusRuntimeField(inactivityTimeouts); + const runtimeField = _buildStatusRuntimeField({ inactivityTimeouts }); expect(runtimeField).toMatchInlineSnapshot(` Object { "status": Object { "script": Object { "lang": "painless", - "source": " - long lastCheckinMillis = doc['last_checkin'].size() > 0 - ? doc['last_checkin'].value.toInstant().toEpochMilli() - : ( - doc['enrolled_at'].size() > 0 - ? doc['enrolled_at'].value.toInstant().toEpochMilli() - : -1 - ); - if (doc['active'].size() > 0 && doc['active'].value == false) { - emit('unenrolled'); - } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && (doc['policy_id'].value == 'policy-1') && lastCheckinMillis < 1234567590123L) { - emit('inactive'); - } else if ( - lastCheckinMillis > 0 - && lastCheckinMillis - < (1234567590123L) - ) { - emit('offline'); - } else if ( - doc['policy_revision_idx'].size() == 0 || ( - doc['upgrade_started_at'].size() > 0 && - doc['upgraded_at'].size() == 0 - ) - ) { - emit('updating'); - } else if (doc['last_checkin'].size() == 0) { - emit('enrolling'); - } else if (doc['unenrollment_started_at'].size() > 0) { - emit('unenrolling'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'error' - ) { - emit('error'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'degraded' - ) { - emit('degraded'); - } else { - emit('online'); - }", + "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() : ( doc['enrolled_at'].size() > 0 ? doc['enrolled_at'].value.toInstant().toEpochMilli() : -1 ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && ['policy-1'].contains(doc['policy_id'].value) && lastCheckinMillis < 1234567590123L) {emit('inactive');} else if ( lastCheckinMillis > 0 && lastCheckinMillis < 1234567590123L ) { emit('offline'); } else if ( doc['policy_revision_idx'].size() == 0 || ( doc['upgrade_started_at'].size() > 0 && doc['upgraded_at'].size() == 0 ) ) { emit('updating'); } else if (doc['last_checkin'].size() == 0) { emit('enrolling'); } else if (doc['unenrollment_started_at'].size() > 0) { emit('unenrolling'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'error' ) { emit('error'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'degraded' ) { emit('degraded'); } else { emit('online'); }", }, "type": "keyword", }, @@ -193,54 +70,37 @@ describe('buildStatusRuntimeField', () => { policyIds: ['policy-1', 'policy-2'], }, ]; - const runtimeField = _buildStatusRuntimeField(inactivityTimeouts); + const runtimeField = _buildStatusRuntimeField({ inactivityTimeouts }); expect(runtimeField).toMatchInlineSnapshot(` Object { "status": Object { "script": Object { "lang": "painless", - "source": " - long lastCheckinMillis = doc['last_checkin'].size() > 0 - ? doc['last_checkin'].value.toInstant().toEpochMilli() - : ( - doc['enrolled_at'].size() > 0 - ? doc['enrolled_at'].value.toInstant().toEpochMilli() - : -1 - ); - if (doc['active'].size() > 0 && doc['active'].value == false) { - emit('unenrolled'); - } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && (doc['policy_id'].value == 'policy-1' || doc['policy_id'].value == 'policy-2') && lastCheckinMillis < 1234567590123L) { - emit('inactive'); - } else if ( - lastCheckinMillis > 0 - && lastCheckinMillis - < (1234567590123L) - ) { - emit('offline'); - } else if ( - doc['policy_revision_idx'].size() == 0 || ( - doc['upgrade_started_at'].size() > 0 && - doc['upgraded_at'].size() == 0 - ) - ) { - emit('updating'); - } else if (doc['last_checkin'].size() == 0) { - emit('enrolling'); - } else if (doc['unenrollment_started_at'].size() > 0) { - emit('unenrolling'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'error' - ) { - emit('error'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'degraded' - ) { - emit('degraded'); - } else { - emit('online'); - }", + "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() : ( doc['enrolled_at'].size() > 0 ? doc['enrolled_at'].value.toInstant().toEpochMilli() : -1 ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && ['policy-1','policy-2'].contains(doc['policy_id'].value) && lastCheckinMillis < 1234567590123L) {emit('inactive');} else if ( lastCheckinMillis > 0 && lastCheckinMillis < 1234567590123L ) { emit('offline'); } else if ( doc['policy_revision_idx'].size() == 0 || ( doc['upgrade_started_at'].size() > 0 && doc['upgraded_at'].size() == 0 ) ) { emit('updating'); } else if (doc['last_checkin'].size() == 0) { emit('enrolling'); } else if (doc['unenrollment_started_at'].size() > 0) { emit('unenrolling'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'error' ) { emit('error'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'degraded' ) { emit('degraded'); } else { emit('online'); }", + }, + "type": "keyword", + }, + } + `); + }); + it('should not perform inactivity check if there are too many agent policies with an inactivity timeout', () => { + const inactivityTimeouts: InactivityTimeouts = [ + { + inactivityTimeout: 300, + // default max is 750 + policyIds: new Array(1000).fill(0).map((_, i) => `policy-${i}`), + }, + ]; + + const runtimeField = _buildStatusRuntimeField({ inactivityTimeouts }); + + expect(runtimeField).not.toContain('policy-'); + expect(runtimeField).toMatchInlineSnapshot(` + Object { + "status": Object { + "script": Object { + "lang": "painless", + "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() : ( doc['enrolled_at'].size() > 0 ? doc['enrolled_at'].value.toInstant().toEpochMilli() : -1 ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if ( lastCheckinMillis > 0 && lastCheckinMillis < 1234567590123L ) { emit('offline'); } else if ( doc['policy_revision_idx'].size() == 0 || ( doc['upgrade_started_at'].size() > 0 && doc['upgraded_at'].size() == 0 ) ) { emit('updating'); } else if (doc['last_checkin'].size() == 0) { emit('enrolling'); } else if (doc['unenrollment_started_at'].size() > 0) { emit('unenrolling'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'error' ) { emit('error'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'degraded' ) { emit('degraded'); } else { emit('online'); }", }, "type": "keyword", }, @@ -258,54 +118,13 @@ describe('buildStatusRuntimeField', () => { policyIds: ['policy-3'], }, ]; - const runtimeField = _buildStatusRuntimeField(inactivityTimeouts); + const runtimeField = _buildStatusRuntimeField({ inactivityTimeouts }); expect(runtimeField).toMatchInlineSnapshot(` Object { "status": Object { "script": Object { "lang": "painless", - "source": " - long lastCheckinMillis = doc['last_checkin'].size() > 0 - ? doc['last_checkin'].value.toInstant().toEpochMilli() - : ( - doc['enrolled_at'].size() > 0 - ? doc['enrolled_at'].value.toInstant().toEpochMilli() - : -1 - ); - if (doc['active'].size() > 0 && doc['active'].value == false) { - emit('unenrolled'); - } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && (doc['policy_id'].value == 'policy-1' || doc['policy_id'].value == 'policy-2') && lastCheckinMillis < 1234567590123L || (doc['policy_id'].value == 'policy-3') && lastCheckinMillis < 1234567490123L) { - emit('inactive'); - } else if ( - lastCheckinMillis > 0 - && lastCheckinMillis - < (1234567590123L) - ) { - emit('offline'); - } else if ( - doc['policy_revision_idx'].size() == 0 || ( - doc['upgrade_started_at'].size() > 0 && - doc['upgraded_at'].size() == 0 - ) - ) { - emit('updating'); - } else if (doc['last_checkin'].size() == 0) { - emit('enrolling'); - } else if (doc['unenrollment_started_at'].size() > 0) { - emit('unenrolling'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'error' - ) { - emit('error'); - } else if ( - doc['last_checkin_status'].size() > 0 && - doc['last_checkin_status'].value.toLowerCase() == 'degraded' - ) { - emit('degraded'); - } else { - emit('online'); - }", + "source": " long lastCheckinMillis = doc['last_checkin'].size() > 0 ? doc['last_checkin'].value.toInstant().toEpochMilli() : ( doc['enrolled_at'].size() > 0 ? doc['enrolled_at'].value.toInstant().toEpochMilli() : -1 ); if (doc['active'].size() > 0 && doc['active'].value == false) { emit('unenrolled'); } else if (lastCheckinMillis > 0 && doc['policy_id'].size() > 0 && ['policy-1','policy-2'].contains(doc['policy_id'].value) && lastCheckinMillis < 1234567590123L || ['policy-3'].contains(doc['policy_id'].value) && lastCheckinMillis < 1234567490123L) {emit('inactive');} else if ( lastCheckinMillis > 0 && lastCheckinMillis < 1234567590123L ) { emit('offline'); } else if ( doc['policy_revision_idx'].size() == 0 || ( doc['upgrade_started_at'].size() > 0 && doc['upgraded_at'].size() == 0 ) ) { emit('updating'); } else if (doc['last_checkin'].size() == 0) { emit('enrolling'); } else if (doc['unenrollment_started_at'].size() > 0) { emit('unenrolling'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'error' ) { emit('error'); } else if ( doc['last_checkin_status'].size() > 0 && doc['last_checkin_status'].value.toLowerCase() == 'degraded' ) { emit('degraded'); } else { emit('online'); }", }, "type": "keyword", }, @@ -314,8 +133,14 @@ describe('buildStatusRuntimeField', () => { }); it('should build the same runtime field if path ends with. or not', () => { const inactivityTimeouts: InactivityTimeouts = []; - const runtimeFieldWithDot = _buildStatusRuntimeField(inactivityTimeouts, 'my.prefix.'); - const runtimeFieldNoDot = _buildStatusRuntimeField(inactivityTimeouts, 'my.prefix'); + const runtimeFieldWithDot = _buildStatusRuntimeField({ + inactivityTimeouts, + pathPrefix: 'my.prefix.', + }); + const runtimeFieldNoDot = _buildStatusRuntimeField({ + inactivityTimeouts, + pathPrefix: 'my.prefix', + }); expect(runtimeFieldWithDot).toEqual(runtimeFieldNoDot); }); }); diff --git a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts index cebf3a440e511..f0f70139c5437 100644 --- a/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts +++ b/x-pack/plugins/fleet/server/services/agents/build_status_runtime_field.ts @@ -7,41 +7,88 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { Logger } from '@kbn/core/server'; import { AGENT_POLLING_THRESHOLD_MS } from '../../constants'; import { agentPolicyService } from '../agent_policy'; +import { appContextService } from '../app_context'; const MISSED_INTERVALS_BEFORE_OFFLINE = 10; const MS_BEFORE_OFFLINE = MISSED_INTERVALS_BEFORE_OFFLINE * AGENT_POLLING_THRESHOLD_MS; - +const DEFAULT_MAX_AGENT_POLICIES_WITH_INACTIVITY_TIMEOUT = 750; export type InactivityTimeouts = Awaited< ReturnType >; -const _buildInactiveClause = ( - now: number, - inactivityTimeouts: InactivityTimeouts, - field: (path: string) => string -) => { +let inactivityTimeoutsDisabled = false; +const _buildInactiveCondition = (opts: { + now: number; + inactivityTimeouts: InactivityTimeouts; + maxAgentPoliciesWithInactivityTimeout: number; + field: (path: string) => string; + logger?: Logger; +}): string | null => { + const { now, inactivityTimeouts, maxAgentPoliciesWithInactivityTimeout, field, logger } = opts; + // if there are no policies with inactivity timeouts, then no agents are inactive + if (inactivityTimeouts.length === 0) { + return null; + } + + const totalAgentPoliciesWithInactivityTimeouts = inactivityTimeouts.reduce( + (total, { policyIds }) => total + policyIds.length, + 0 + ); + + // if too many agent policies have inactivity timeouts, then we can't use the inactivity timeout + // as the query becomes too large see github.com/elastic/kibana/issues/150577 + if (totalAgentPoliciesWithInactivityTimeouts > maxAgentPoliciesWithInactivityTimeout) { + if (!inactivityTimeoutsDisabled) { + // only log this once as this function is executed a lot + logger?.warn( + `There are ${totalAgentPoliciesWithInactivityTimeouts} agent policies with an inactivity timeout set but the maximum allowed is ${maxAgentPoliciesWithInactivityTimeout}. Agents will not be marked as inactive.` + ); + inactivityTimeoutsDisabled = true; + } + return null; + } + + if (inactivityTimeoutsDisabled) { + logger?.info( + `There are ${totalAgentPoliciesWithInactivityTimeouts} agent policies which is now below the maximum allowed of ${maxAgentPoliciesWithInactivityTimeout}. Agents will now be marked as inactive again.` + ); + inactivityTimeoutsDisabled = false; + } + const policyClauses = inactivityTimeouts .map(({ inactivityTimeout, policyIds }) => { const inactivityTimeoutMs = inactivityTimeout * 1000; - const policyOrs = policyIds - .map((policyId) => `${field('policy_id')}.value == '${policyId}'`) - .join(' || '); + const policyIdMatches = `[${policyIds.map((id) => `'${id}'`).join(',')}].contains(${field( + 'policy_id' + )}.value)`; - return `(${policyOrs}) && lastCheckinMillis < ${now - inactivityTimeoutMs}L`; + return `${policyIdMatches} && lastCheckinMillis < ${now - inactivityTimeoutMs}L`; }) .join(' || '); - const agentIsInactive = policyClauses.length ? `${policyClauses}` : 'false'; // if no policies have inactivity timeouts, then no agents are inactive - - return `lastCheckinMillis > 0 && ${field('policy_id')}.size() > 0 && ${agentIsInactive}`; + return `lastCheckinMillis > 0 && ${field('policy_id')}.size() > 0 && ${policyClauses}`; }; -function _buildSource(inactivityTimeouts: InactivityTimeouts, pathPrefix?: string) { +function _buildSource( + inactivityTimeouts: InactivityTimeouts, + maxAgentPoliciesWithInactivityTimeout: number, + pathPrefix?: string, + logger?: Logger +) { const normalizedPrefix = pathPrefix ? `${pathPrefix}${pathPrefix.endsWith('.') ? '' : '.'}` : ''; const field = (path: string) => `doc['${normalizedPrefix + path}']`; const now = Date.now(); + const agentIsInactiveCondition = _buildInactiveCondition({ + now, + inactivityTimeouts, + maxAgentPoliciesWithInactivityTimeout, + field, + logger, + }); + return ` long lastCheckinMillis = ${field('last_checkin')}.size() > 0 ? ${field('last_checkin')}.value.toInstant().toEpochMilli() @@ -52,12 +99,11 @@ function _buildSource(inactivityTimeouts: InactivityTimeouts, pathPrefix?: strin ); if (${field('active')}.size() > 0 && ${field('active')}.value == false) { emit('unenrolled'); - } else if (${_buildInactiveClause(now, inactivityTimeouts, field)}) { - emit('inactive'); - } else if ( + } ${agentIsInactiveCondition ? `else if (${agentIsInactiveCondition}) {emit('inactive');}` : ''} + else if ( lastCheckinMillis > 0 && lastCheckinMillis - < (${now - MS_BEFORE_OFFLINE}L) + < ${now - MS_BEFORE_OFFLINE}L ) { emit('offline'); } else if ( @@ -83,15 +129,28 @@ function _buildSource(inactivityTimeouts: InactivityTimeouts, pathPrefix?: strin emit('degraded'); } else { emit('online'); - }`; + }`.replace(/\s{2,}/g, ' '); // replace newlines and double spaces to save characters } // exported for testing -export function _buildStatusRuntimeField( - inactivityTimeouts: InactivityTimeouts, - pathPrefix?: string -): NonNullable { - const source = _buildSource(inactivityTimeouts, pathPrefix); +export function _buildStatusRuntimeField(opts: { + inactivityTimeouts: InactivityTimeouts; + maxAgentPoliciesWithInactivityTimeout?: number; + pathPrefix?: string; + logger?: Logger; +}): NonNullable { + const { + inactivityTimeouts, + maxAgentPoliciesWithInactivityTimeout = DEFAULT_MAX_AGENT_POLICIES_WITH_INACTIVITY_TIMEOUT, + pathPrefix, + logger, + } = opts; + const source = _buildSource( + inactivityTimeouts, + maxAgentPoliciesWithInactivityTimeout, + pathPrefix, + logger + ); return { status: { type: 'keyword', @@ -111,7 +170,23 @@ export async function buildAgentStatusRuntimeField( soClient: SavedObjectsClientContract, pathPrefix?: string ) { + const config = appContextService.getConfig(); + + let logger: Logger | undefined; + try { + logger = appContextService.getLogger(); + } catch (e) { + // ignore, logger is optional + // this code can be used and tested without an app context + } + const maxAgentPoliciesWithInactivityTimeout = + config?.developer?.maxAgentPoliciesWithInactivityTimeout; const inactivityTimeouts = await agentPolicyService.getInactivityTimeouts(soClient); - return _buildStatusRuntimeField(inactivityTimeouts, pathPrefix); + return _buildStatusRuntimeField({ + inactivityTimeouts, + maxAgentPoliciesWithInactivityTimeout, + pathPrefix, + logger, + }); } 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 30c56b53640af..3ef1a269d8e6f 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,14 +16,11 @@ import { updateAgentTags } from './update_agent_tags'; import { UpdateAgentTagsActionRunner, updateTagsBatch } from './update_agent_tags_action_runner'; jest.mock('../app_context', () => { + const { loggerMock } = jest.requireActual('@kbn/logging-mocks'); return { appContextService: { - getLogger: jest.fn().mockReturnValue({ - debug: jest.fn(), - warn: jest.fn(), - info: jest.fn(), - error: jest.fn(), - } as any), + getLogger: () => loggerMock.create(), + getConfig: () => {}, }, }; }); diff --git a/x-pack/test/fleet_api_integration/apis/agents/status.ts b/x-pack/test/fleet_api_integration/apis/agents/status.ts index b110871275504..89a3a67bbf3f5 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/status.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/status.ts @@ -257,5 +257,54 @@ export default function ({ getService }: FtrProviderContext) { statusCode: 403, }); }); + + it('should not perform inactivity check if there are too many agent policies with inactivity timeout', async () => { + // the test server is started with --xpack.fleet.developer.maxAgentPoliciesWithInactivityTimeout=10 + // so we create 11 policies with inactivity timeout then no agents should turn inactive + + const policiesToAdd = new Array(11).fill(0).map((_, i) => `policy-inactivity-timeout-${i}`); + + await Promise.all( + policiesToAdd.map((policyId) => + es.create({ + id: 'ingest-agent-policies:' + policyId, + index: '.kibana', + refresh: 'wait_for', + document: { + type: 'ingest-agent-policies', + 'ingest-agent-policies': { + name: policyId, + namespace: 'default', + description: 'Policy with inactivity timeout', + status: 'active', + is_default: true, + monitoring_enabled: ['logs', 'metrics'], + revision: 2, + updated_at: '2020-05-07T19:34:42.533Z', + updated_by: 'system', + inactivity_timeout: 60, + }, + migrationVersion: { + 'ingest-agent-policies': '7.10.0', + }, + }, + }) + ) + ); + const { body: apiResponse } = await supertest.get(`/api/fleet/agent_status`).expect(200); + expect(apiResponse).to.eql({ + results: { + events: 0, + other: 0, + total: 10, + online: 3, + error: 2, + offline: 1, + updating: 4, + inactive: 0, + unenrolled: 1, + }, + }); + }); }); } diff --git a/x-pack/test/fleet_api_integration/config.ts b/x-pack/test/fleet_api_integration/config.ts index ed7c90f96bc38..77c3860ba0fa1 100644 --- a/x-pack/test/fleet_api_integration/config.ts +++ b/x-pack/test/fleet_api_integration/config.ts @@ -69,6 +69,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...(registryPort ? [`--xpack.fleet.registryUrl=http://localhost:${registryPort}`] : []), `--xpack.fleet.developer.bundledPackageLocation=${BUNDLED_PACKAGE_DIR}`, '--xpack.cloudSecurityPosture.enabled=true', + `--xpack.fleet.developer.maxAgentPoliciesWithInactivityTimeout=10`, `--xpack.fleet.packageVerification.gpgKeyPath=${getFullPath( './apis/fixtures/package_verification/signatures/fleet_test_key_public.asc' )}`, From 01b11cff6ab744d9403ba97e7f259d04162979ba Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 14 Feb 2023 14:06:22 +0000 Subject: [PATCH 177/203] [ML] trained_models_spaces api tests (#151026) Adding api tests for `/api/ml/saved_objects/trained_models_spaces` Related to https://github.com/elastic/kibana/issues/147170 --- .../{jobs_spaces.ts => get_jobs_spaces.ts} | 0 .../saved_objects/get_trained_model_spaces.ts | 83 +++++++++++++++++++ .../apis/ml/saved_objects/index.ts | 3 +- 3 files changed, 85 insertions(+), 1 deletion(-) rename x-pack/test/api_integration/apis/ml/saved_objects/{jobs_spaces.ts => get_jobs_spaces.ts} (100%) create mode 100644 x-pack/test/api_integration/apis/ml/saved_objects/get_trained_model_spaces.ts diff --git a/x-pack/test/api_integration/apis/ml/saved_objects/jobs_spaces.ts b/x-pack/test/api_integration/apis/ml/saved_objects/get_jobs_spaces.ts similarity index 100% rename from x-pack/test/api_integration/apis/ml/saved_objects/jobs_spaces.ts rename to x-pack/test/api_integration/apis/ml/saved_objects/get_jobs_spaces.ts diff --git a/x-pack/test/api_integration/apis/ml/saved_objects/get_trained_model_spaces.ts b/x-pack/test/api_integration/apis/ml/saved_objects/get_trained_model_spaces.ts new file mode 100644 index 0000000000000..7f18b518d063b --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/saved_objects/get_trained_model_spaces.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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'; +import { USER } from '../../../../functional/services/ml/security_common'; +import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api'; + +export default ({ getService }: FtrProviderContext) => { + const ml = getService('ml'); + const spacesService = getService('spaces'); + const supertest = getService('supertestWithoutAuth'); + + const trainedModelIdSpace1 = 'trained_model_single_space1'; + const trainedModelIdSpace2 = 'trained_model_single_space2'; + const idSpace1 = 'space1'; + const idSpace2 = 'space2'; + const langIdent = 'lang_ident_model_1'; + + async function runRequest(expectedStatusCode: number, user: USER) { + const { body, status } = await supertest + .get(`/api/ml/saved_objects/trained_models_spaces`) + .auth(user, ml.securityCommon.getPasswordForUser(user)) + .set(COMMON_REQUEST_HEADERS); + + ml.api.assertResponseStatusCode(expectedStatusCode, status, body); + + return body; + } + + describe('GET saved_objects/trained_models_spaces', () => { + before(async () => { + await ml.testResources.setKibanaTimeZoneToUTC(); + + await spacesService.create({ id: idSpace1, name: 'space_one', disabledFeatures: [] }); + await spacesService.create({ id: idSpace2, name: 'space_two', disabledFeatures: [] }); + + const trainedModelConfig1 = ml.api.createTestTrainedModelConfig( + trainedModelIdSpace1, + 'regression' + ); + await ml.api.createTrainedModel(trainedModelIdSpace1, trainedModelConfig1.body, idSpace1); + + const trainedModelConfig2 = ml.api.createTestTrainedModelConfig( + trainedModelIdSpace2, + 'regression' + ); + await ml.api.createTrainedModel(trainedModelIdSpace2, trainedModelConfig2.body, idSpace2); + }); + + after(async () => { + await spacesService.delete(idSpace1); + await spacesService.delete(idSpace2); + await ml.api.cleanMlIndices(); + await ml.testResources.cleanMLSavedObjects(); + }); + + it('should list all trained models for user with access to all spaces', async () => { + const body = await runRequest(200, USER.ML_VIEWER_ALL_SPACES); + + expect(body).to.have.property('trainedModels'); + expect(body.trainedModels).to.eql({ + [langIdent]: ['*'], + [trainedModelIdSpace1]: [idSpace1], + [trainedModelIdSpace2]: [idSpace2], + }); + }); + + it('should only list trained models for the space the user has access to', async () => { + const body = await runRequest(200, USER.ML_VIEWER_SPACE1); + + expect(body).to.have.property('trainedModels'); + expect(body.trainedModels).to.eql({ + [langIdent]: ['*'], + [trainedModelIdSpace1]: [idSpace1], + }); + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/ml/saved_objects/index.ts b/x-pack/test/api_integration/apis/ml/saved_objects/index.ts index 32c83cb624163..b4b8e1d0653f3 100644 --- a/x-pack/test/api_integration/apis/ml/saved_objects/index.ts +++ b/x-pack/test/api_integration/apis/ml/saved_objects/index.ts @@ -9,9 +9,10 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('saved objects', function () { - loadTestFile(require.resolve('./jobs_spaces')); + loadTestFile(require.resolve('./get_jobs_spaces')); loadTestFile(require.resolve('./can_delete_job')); loadTestFile(require.resolve('./can_delete_trained_model')); + loadTestFile(require.resolve('./get_trained_model_spaces')); loadTestFile(require.resolve('./initialize_jobs')); loadTestFile(require.resolve('./initialize_trained_models')); loadTestFile(require.resolve('./status')); From 12efa3584743e67fc474dc57edbbb6d2b6182b5a Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Tue, 14 Feb 2023 15:33:55 +0100 Subject: [PATCH 178/203] [ML] Allow splitting by field of `ip` type for Change point detection (#151022) ## Summary Follow-up for https://github.com/elastic/kibana/pull/150308 Resolves https://github.com/elastic/kibana/issues/145703 Allows splitting by field of `ip` type for Change point detection --- .../change_point_detection_context.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx index 7c4980846a8d8..a30ef3cc4a997 100644 --- a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx +++ b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_context.tsx @@ -20,6 +20,7 @@ import type { Filter, Query } from '@kbn/es-query'; import { usePageUrlState } from '@kbn/ml-url-state'; import { useTimefilter, useTimeRangeUpdates } from '@kbn/ml-date-picker'; import moment from 'moment'; +import { ES_FIELD_TYPES } from '@kbn/field-types'; import { DEFAULT_AGG_FUNCTION } from './constants'; import { useSplitFieldCardinality } from './use_split_field_cardinality'; import { @@ -163,7 +164,9 @@ export const ChangePointDetectionContextProvider: FC = ({ children }) => { ({ aggregatable, esTypes, displayName }) => aggregatable && esTypes && - esTypes.includes('keyword') && + esTypes.some((el) => + [ES_FIELD_TYPES.KEYWORD, ES_FIELD_TYPES.IP].includes(el as ES_FIELD_TYPES) + ) && !['_id', '_index'].includes(displayName) ); }, [dataView]); From 26a753808a74cf447592bffa251f498247671d1d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Feb 2023 08:39:48 -0600 Subject: [PATCH 179/203] Update dependency terser to ^5.16.3 (main) (#150399) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [terser](https://terser.org) ([source](https://togithub.com/terser/terser)) | [`^5.16.1` -> `^5.16.3`](https://renovatebot.com/diffs/npm/terser/5.16.1/5.16.3) | [![age](https://badges.renovateapi.com/packages/npm/terser/5.16.3/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/terser/5.16.3/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/terser/5.16.3/compatibility-slim/5.16.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/terser/5.16.3/confidence-slim/5.16.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
    terser/terser ### [`v5.16.3`](https://togithub.com/terser/terser/blob/HEAD/CHANGELOG.md#v5163) [Compare Source](https://togithub.com/terser/terser/compare/v5.16.2...v5.16.3) - Ensure function definitions, don't assume the values of variables defined after them. ### [`v5.16.2`](https://togithub.com/terser/terser/blob/HEAD/CHANGELOG.md#v5162) [Compare Source](https://togithub.com/terser/terser/compare/v5.16.1...v5.16.2) - Fix sourcemaps with non-ascii characters ([#​1318](https://togithub.com/terser/terser/issues/1318)) - Support string module name and export \* as ([#​1336](https://togithub.com/terser/terser/issues/1336)) - Do not move `let` out of `for` initializers, as it can change scoping - Fix a corner case that would generate the invalid syntax `if (something) let x` ("let" in braceless if body) - Knowledge of more native object properties ([#​1330](https://togithub.com/terser/terser/issues/1330)) - Got rid of Travis ([#​1323](https://togithub.com/terser/terser/issues/1323)) - Added semi-secret `asObject` sourcemap option to typescript defs ([#​1321](https://togithub.com/terser/terser/issues/1321))
    --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View repository job log [here](https://app.renovatebot.com/dashboard#github/elastic/kibana). --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jonathan Budzenski --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a3e5a3b5f6e33..ea120b03ecc69 100644 --- a/package.json +++ b/package.json @@ -1455,7 +1455,7 @@ "svgo": "^2.8.0", "tape": "^5.0.1", "tempy": "^0.3.0", - "terser": "^5.16.1", + "terser": "^5.16.3", "terser-webpack-plugin": "^4.2.3", "tough-cookie": "^4.1.2", "tree-kill": "^1.2.2", diff --git a/yarn.lock b/yarn.lock index 405c3ad9bf181..813b70a2205a8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27284,10 +27284,10 @@ terser@^4.1.2, terser@^4.6.3: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^5.14.1, terser@^5.16.1, terser@^5.3.4, terser@^5.9.0: - version "5.16.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.1.tgz#5af3bc3d0f24241c7fb2024199d5c461a1075880" - integrity sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw== +terser@^5.14.1, terser@^5.16.3, terser@^5.3.4, terser@^5.9.0: + version "5.16.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.3.tgz#3266017a9b682edfe019b8ecddd2abaae7b39c6b" + integrity sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q== dependencies: "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" From 25d4c9f3297bfcf685287d4b0fd3a91934d8eb04 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 14 Feb 2023 14:40:46 +0000 Subject: [PATCH 180/203] [Fleet] Warn user when they are sending data to stream managed by different integration (#151075) ## Summary Closes #149427 Give the user a warning if they are sending data to a data stream that isn't managed by the integration being added. Screenshot 2023-02-13 at 21 17 13 --- .../steps/components/dataset_combo.tsx | 77 ++++++++++++++----- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/dataset_combo.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/dataset_combo.tsx index 6908f8fea130f..c310cf2b29d3a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/dataset_combo.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/components/dataset_combo.tsx @@ -6,9 +6,11 @@ */ import React, { useEffect, useState } from 'react'; -import { EuiComboBox } from '@elastic/eui'; +import { EuiComboBox, EuiIcon, EuiLink, EuiSpacer, EuiText, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + import type { DataStream } from '../../../../../../../../../common/types'; interface SelectedDataset { @@ -73,24 +75,59 @@ export const DatasetComboBox: React.FC<{ }); }; return ( - + <> + + {valueAsOption && valueAsOption.value.package !== pkgName && ( + <> + + + +   + + } + > + + {i18n.translate('xpack.fleet.datasetCombo.learnMoreLink', { + defaultMessage: 'learn more', + })} + + + ), + }} + /> + + + )} + ); }; From ee26923aabe418107f08c2525f365741e2fa9ef7 Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Tue, 14 Feb 2023 16:11:14 +0100 Subject: [PATCH 181/203] [Defend Workflows] Fix saved queries 500 (#150426) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Bug** Calling `/api/osquery/saved_queries` with `sortOrder` but without `sort` field (`/api/osquery/saved_queries?sortOrder=desc`) was causing 500 server error. Same with calls without any parameters (`/api/osquery/saved_queries`) **Cause** We had defaults failover set for `sortOrder` but not for `sort`. Sorting logic required both fields to be defined. All schema params were set to optional and we were validating them ourselves. **Fix** I've tightened the schema by making all the params required and provided default values if not provided. `page: schema.number({ defaultValue: 1 }), sort: schema.string({ defaultValue: 'id' }), sortOrder: schema.oneOf([schema.literal('asc'), schema.literal('desc')], {defaultValue: 'desc',}),` **Additionally** Outdated osQuery API docs - `perPage` became `pageSize` and `sortField` became `sort`. Also, minor spelling fixes. --------- Co-authored-by: Patryk Kopyciński --- .../live-queries/get-all.asciidoc | 6 +- .../osquery-manager/packs/get-all.asciidoc | 4 +- .../saved-queries/create.asciidoc | 2 +- .../saved-queries/get-all.asciidoc | 4 +- .../saved-queries/update.asciidoc | 2 +- .../saved_query/find_saved_query_route.ts | 73 +++++++++++-------- 6 files changed, 50 insertions(+), 41 deletions(-) diff --git a/docs/api/osquery-manager/live-queries/get-all.asciidoc b/docs/api/osquery-manager/live-queries/get-all.asciidoc index 7415518438b6d..58845d3c498e6 100644 --- a/docs/api/osquery-manager/live-queries/get-all.asciidoc +++ b/docs/api/osquery-manager/live-queries/get-all.asciidoc @@ -28,10 +28,10 @@ experimental[] Get live queries. `page`:: (Optional, integer) The page number to return. The default is `1`. -`perPage`:: +`pageSize`:: (Optional, integer) The number of rules to return per page. The default is `20`. -`sortField`:: +`sort`:: (Optional, string) The field that is used to sort the results. Options include `createdAt` or `updatedAt`. The default is `createdAt`. + @@ -41,7 +41,7 @@ query. `sortOrder`:: (Optional, string) Specified the sort order. Options include `desc` or `asc`. -The defaults is `desc`. +The default is `desc`. [[osquery-manager-live-queries-api-get-all-codes]] diff --git a/docs/api/osquery-manager/packs/get-all.asciidoc b/docs/api/osquery-manager/packs/get-all.asciidoc index c0b573e59c69c..44c36947f46b0 100644 --- a/docs/api/osquery-manager/packs/get-all.asciidoc +++ b/docs/api/osquery-manager/packs/get-all.asciidoc @@ -27,10 +27,10 @@ experimental[] Get packs. `page`:: (Optional, integer) The page number to return. The default is `1`. -`perPage`:: +`pageSize`:: (Optional, integer) The number of rules to return per page. The default is `20`. -`sortField`:: +`sort`:: (Optional, string) Specifies the field that sorts the results. Options include `createdAt` or `updatedAt`. The default is `createdAt`. + diff --git a/docs/api/osquery-manager/saved-queries/create.asciidoc b/docs/api/osquery-manager/saved-queries/create.asciidoc index f2604ecf5dc0a..61f415845a5aa 100644 --- a/docs/api/osquery-manager/saved-queries/create.asciidoc +++ b/docs/api/osquery-manager/saved-queries/create.asciidoc @@ -35,7 +35,7 @@ experimental[] Create saved queries. `version`:: (Optional, string) Uses the Osquery versions greater than or equal to the specified version string. -`internal`:: (Optional, string) An interval, in seconds, to run the query. +`interval`:: (Optional, integer) An interval, in seconds, to run the query. `ecs_mapping`:: (Optional, object) Maps Osquery results columns or static values to ECS fields. diff --git a/docs/api/osquery-manager/saved-queries/get-all.asciidoc b/docs/api/osquery-manager/saved-queries/get-all.asciidoc index 8212bf845f8c4..3fc8d1d5da93c 100644 --- a/docs/api/osquery-manager/saved-queries/get-all.asciidoc +++ b/docs/api/osquery-manager/saved-queries/get-all.asciidoc @@ -27,10 +27,10 @@ experimental[] Get saved queries. `page`:: (Optional, integer) The page number to return. The default is `1`. -`perPage`:: +`pageSize`:: (Optional, integer) The number of rules to return per page. The default is `20`. -`sortField`:: +`sort`:: (Optional, string) Specifies the field that sorts the results. Options include `createdAt` or `updatedAt`. The default is `createdAt`. + diff --git a/docs/api/osquery-manager/saved-queries/update.asciidoc b/docs/api/osquery-manager/saved-queries/update.asciidoc index f9f9916179d95..025a69b28e0f0 100644 --- a/docs/api/osquery-manager/saved-queries/update.asciidoc +++ b/docs/api/osquery-manager/saved-queries/update.asciidoc @@ -40,7 +40,7 @@ WARNING: You are unable to update a prebuilt saved query (`prebuilt = true`). `version`:: (Optional, string) Runs on Osquery versions greater than or equal to the specified version string. -`internal`:: (Optional, string) The interval, in seconds, to run the query. +`interval`:: (Optional, integer) The interval, in seconds, to run the query. `ecs_mapping`:: (Optional, object) Maps Osquery result columns or static values to ECS fields. diff --git a/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts b/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts index 4acec0af1e35d..79ec614b443d3 100644 --- a/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/saved_query/find_saved_query_route.ts @@ -21,10 +21,12 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC path: '/api/osquery/saved_queries', validate: { query: schema.object({ - page: schema.maybe(schema.number()), + page: schema.number({ defaultValue: 1 }), pageSize: schema.maybe(schema.number()), - sort: schema.maybe(schema.string()), - sortOrder: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), + sort: schema.string({ defaultValue: 'id' }), + sortOrder: schema.oneOf([schema.literal('asc'), schema.literal('desc')], { + defaultValue: 'desc', + }), }), }, options: { tags: [`access:${PLUGIN_ID}-readSavedQueries`] }, @@ -33,40 +35,47 @@ export const findSavedQueryRoute = (router: IRouter, osqueryContext: OsqueryAppC const coreContext = await context.core; const savedObjectsClient = coreContext.savedObjects.client; - const savedQueries = await savedObjectsClient.find<{ - ecs_mapping: Array<{ field: string; value: string }>; - prebuilt: boolean; - }>({ - type: savedQuerySavedObjectType, - page: request.query.page ?? 1, - perPage: request.query.pageSize, - sortField: request.query.sort, - sortOrder: request.query.sortOrder ?? 'desc', - }); + try { + const savedQueries = await savedObjectsClient.find<{ + ecs_mapping: Array<{ field: string; value: string }>; + prebuilt: boolean; + }>({ + type: savedQuerySavedObjectType, + page: request.query.page, + perPage: request.query.pageSize, + sortField: request.query.sort, + sortOrder: request.query.sortOrder, + }); - const prebuiltSavedQueriesMap = await getInstalledSavedQueriesMap( - osqueryContext.service.getPackageService()?.asInternalUser - ); - const savedObjects = savedQueries.saved_objects.map((savedObject) => { - // eslint-disable-next-line @typescript-eslint/naming-convention - const ecs_mapping = savedObject.attributes.ecs_mapping; + const prebuiltSavedQueriesMap = await getInstalledSavedQueriesMap( + osqueryContext.service.getPackageService()?.asInternalUser + ); + const savedObjects = savedQueries.saved_objects.map((savedObject) => { + // eslint-disable-next-line @typescript-eslint/naming-convention + const ecs_mapping = savedObject.attributes.ecs_mapping; - savedObject.attributes.prebuilt = !!prebuiltSavedQueriesMap[savedObject.id]; + savedObject.attributes.prebuilt = !!prebuiltSavedQueriesMap[savedObject.id]; - if (ecs_mapping) { - // @ts-expect-error update types - savedObject.attributes.ecs_mapping = convertECSMappingToObject(ecs_mapping); - } + if (ecs_mapping) { + // @ts-expect-error update types + savedObject.attributes.ecs_mapping = convertECSMappingToObject(ecs_mapping); + } - return savedObject; - }); + return savedObject; + }); - return response.ok({ - body: { - ...omit(savedQueries, 'saved_objects'), - data: savedObjects, - }, - }); + return response.ok({ + body: { + ...omit(savedQueries, 'saved_objects'), + data: savedObjects, + }, + }); + } catch (e) { + return response.customError({ + statusCode: e.statusCode || e.output?.statusCode || 500, + body: e, + }); + } } ); }; From 8e1754e0b9d8619dfd0286c29e6b0552118926cf Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Tue, 14 Feb 2023 16:11:46 +0100 Subject: [PATCH 182/203] [Defend Workflows] Parse query params in take actions (#150986) Fixes https://github.com/elastic/security-team/issues/5999 --------- Co-authored-by: Patryk Kopycinski Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../common/utils/replace_params_query.ts | 10 +++++-- .../osquery/cypress/e2e/all/alerts.cy.ts | 19 ++++++++++++ .../osquery/cypress/e2e/all/cases.cy.ts | 24 ++++----------- .../osquery/cypress/tasks/live_query.ts | 16 +++++++++- .../public/components/osquery_schema_link.tsx | 2 +- .../handlers/action/create_action_handler.ts | 30 ++++++++++++------- .../handlers/action/create_queries.test.ts | 8 ++--- .../server/handlers/action/create_queries.ts | 14 ++++----- x-pack/plugins/osquery/server/plugin.ts | 8 +++-- .../live_query/create_live_query_route.ts | 21 ++++++++----- x-pack/plugins/osquery/server/types.ts | 7 +++-- x-pack/plugins/osquery/tsconfig.json | 1 - .../schedule_notification_response_actions.ts | 17 ++++++----- .../plugins/security_solution/tsconfig.json | 1 - 14 files changed, 111 insertions(+), 67 deletions(-) diff --git a/x-pack/plugins/osquery/common/utils/replace_params_query.ts b/x-pack/plugins/osquery/common/utils/replace_params_query.ts index 2f7df42e6a3b1..3c99daf5ec3cf 100644 --- a/x-pack/plugins/osquery/common/utils/replace_params_query.ts +++ b/x-pack/plugins/osquery/common/utils/replace_params_query.ts @@ -7,9 +7,10 @@ import { each, get } from 'lodash'; +const CONTAINS_DYNAMIC_PARAMETER_REGEX = /\{{([^}]+)\}}/g; // when there are 2 opening and 2 closing curly brackets (including brackets) + export const replaceParamsQuery = (query: string, data: object) => { - const regex = /\{{([^}]+)\}}/g; // when there are 2 opening and 2 closing curly brackets (including brackets) - const matchedBrackets = query.match(regex); + const matchedBrackets = query.match(new RegExp(CONTAINS_DYNAMIC_PARAMETER_REGEX)); let resultQuery = query; if (matchedBrackets) { @@ -24,10 +25,13 @@ export const replaceParamsQuery = (query: string, data: object) => { }); } - const skipped = regex.test(resultQuery); + const skipped = new RegExp(CONTAINS_DYNAMIC_PARAMETER_REGEX).test(resultQuery); return { result: resultQuery, skipped, }; }; + +export const containsDynamicQuery = (query: string) => + new RegExp(CONTAINS_DYNAMIC_PARAMETER_REGEX).test(query); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts index a76e09a2cd5e2..e772217819e7d 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts @@ -267,6 +267,25 @@ describe('Alert Event Details', () => { cy.contains("SELECT * FROM os_version where name='Ubuntu';"); }); + it('should substitute parameters in live query', () => { + loadAlertsEvents(); + cy.getBySel('expand-event').first().click({ force: true }); + cy.getBySel('take-action-dropdown-btn').click(); + cy.getBySel('osquery-action-item').click(); + cy.contains('1 agent selected.'); + inputQuery("SELECT * FROM os_version where name='{{host.os.name}}';", { + parseSpecialCharSequences: false, + }); + cy.contains('Advanced').click(); + typeInECSFieldInput('tags{downArrow}{enter}'); + cy.getBySel('osqueryColumnValueSelect').type('platform_like{downArrow}{enter}'); + cy.wait(1000); + submitQuery(); + cy.getBySel('dataGridHeader').within(() => { + cy.contains('tags'); + }); + }); + it('sees osquery results from last action', () => { toggleRuleOffAndOn(RULE_NAME); cy.wait(2000); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts index 4dd970042bb8f..e0987550d10dd 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { checkResults } from '../../tasks/live_query'; +import { addLastLiveQueryToCase, checkResults } from '../../tasks/live_query'; import { navigateTo } from '../../tasks/navigation'; import { ArchiverMethod, runKbnArchiverScript } from '../../tasks/archiver'; import { login } from '../../tasks/login'; @@ -23,20 +23,13 @@ describe('Add to Cases', () => { runKbnArchiverScript(ArchiverMethod.UNLOAD, 'case_observability'); }); it('should add result a case and not have add to timeline in result', () => { - cy.waitForReact(); - cy.react('CustomItemAction', { - props: { index: 1 }, - }).click(); - cy.contains('Live query details'); - cy.contains('Add to Case').click(); - cy.contains('Select case'); - cy.contains(/Select$/).click(); + addLastLiveQueryToCase(); cy.contains('Test Obs case has been updated'); cy.visit('/app/observability/cases'); cy.contains('Test Obs case').click(); checkResults(); cy.contains('attached Osquery results'); - cy.contains('select * from uptime;'); + cy.contains("SELECT * FROM os_version where name='Ubuntu';"); cy.contains('View in Discover').should('exist'); cy.contains('View in Lens').should('exist'); cy.contains('Add to Case').should('not.exist'); @@ -55,20 +48,13 @@ describe('Add to Cases', () => { }); it('should add result a case and have add to timeline in result', () => { - cy.waitForReact(); - cy.react('CustomItemAction', { - props: { index: 1 }, - }).click(); - cy.contains('Live query details'); - cy.contains('Add to Case').click(); - cy.contains('Select case'); - cy.contains(/Select$/).click(); + addLastLiveQueryToCase(); cy.contains('Test Security Case has been updated'); cy.visit('/app/security/cases'); cy.contains('Test Security Case').click(); checkResults(); cy.contains('attached Osquery results'); - cy.contains('select * from uptime;'); + cy.contains("SELECT * FROM os_version where name='Ubuntu';"); cy.contains('View in Discover').should('exist'); cy.contains('View in Lens').should('exist'); cy.contains('Add to Case').should('not.exist'); diff --git a/x-pack/plugins/osquery/cypress/tasks/live_query.ts b/x-pack/plugins/osquery/cypress/tasks/live_query.ts index b9d9fe581b76d..4dab249871a3b 100644 --- a/x-pack/plugins/osquery/cypress/tasks/live_query.ts +++ b/x-pack/plugins/osquery/cypress/tasks/live_query.ts @@ -23,7 +23,8 @@ export const selectAllAgents = () => { export const clearInputQuery = () => cy.get(LIVE_QUERY_EDITOR).click().type(`{selectall}{backspace}`); -export const inputQuery = (query: string) => cy.get(LIVE_QUERY_EDITOR).type(query); +export const inputQuery = (query: string, options?: { parseSpecialCharSequences: boolean }) => + cy.get(LIVE_QUERY_EDITOR).type(query, options); export const submitQuery = () => { cy.wait(1000); // wait for the validation to trigger - cypress is way faster than users ;) @@ -90,3 +91,16 @@ export const loadAlertsEvents = () => { cy.get(`[data-is-loading="true"]`).should('not.exist'); }); }; + +export const addLastLiveQueryToCase = () => { + cy.waitForReact(); + cy.react('CustomItemAction', { + props: { index: 1 }, + }) + .first() + .click(); + cy.contains('Live query details'); + cy.contains('Add to Case').click(); + cy.contains('Select case'); + cy.contains(/Select$/).click(); +}; diff --git a/x-pack/plugins/osquery/public/components/osquery_schema_link.tsx b/x-pack/plugins/osquery/public/components/osquery_schema_link.tsx index 53e1cfe220567..09e1be0923e45 100644 --- a/x-pack/plugins/osquery/public/components/osquery_schema_link.tsx +++ b/x-pack/plugins/osquery/public/components/osquery_schema_link.tsx @@ -11,7 +11,7 @@ import React from 'react'; export const OsquerySchemaLink = React.memo(() => ( - + diff --git a/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts b/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts index a26bc88a0d29f..4974fc21b440b 100644 --- a/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts +++ b/x-pack/plugins/osquery/server/handlers/action/create_action_handler.ts @@ -9,7 +9,12 @@ import { v4 as uuidv4 } from 'uuid'; import moment from 'moment'; import { filter, flatten, isEmpty, map, omit, pick, pickBy, some } from 'lodash'; import { AGENT_ACTIONS_INDEX } from '@kbn/fleet-plugin/common'; -import type { Ecs, SavedObjectsClientContract } from '@kbn/core/server'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; +import { + containsDynamicQuery, + replaceParamsQuery, +} from '../../../common/utils/replace_params_query'; import { createDynamicQueries, createQueries } from './create_queries'; import { getInternalSavedObjectsClient } from '../../routes/utils'; import { parseAgentSelection } from '../../lib/parse_agent_groups'; @@ -28,7 +33,7 @@ interface Metadata { interface CreateActionHandlerOptions { soClient?: SavedObjectsClientContract; metadata?: Metadata; - ecsData?: Ecs; + alertData?: ParsedTechnicalFields; } export const createActionHandler = async ( @@ -41,7 +46,7 @@ export const createActionHandler = async ( const internalSavedObjectsClient = await getInternalSavedObjectsClient( osqueryContext.getStartServices ); - const { soClient, metadata, ecsData } = options; + const { soClient, metadata, alertData } = options; const savedObjectsClient = soClient ?? coreStartServices.savedObjects.createInternalRepository(); // eslint-disable-next-line @typescript-eslint/naming-convention @@ -88,22 +93,27 @@ export const createActionHandler = async ( ? !!some(packSO?.references, ['type', 'osquery-pack-asset']) : undefined, queries: packSO - ? map(convertSOQueriesToPack(packSO.attributes.queries), (packQuery, packQueryId) => - pickBy( + ? map(convertSOQueriesToPack(packSO.attributes.queries), (packQuery, packQueryId) => { + const dynamicQueryPresent = packQuery.query && containsDynamicQuery(packQuery.query); + + return pickBy( { action_id: uuidv4(), id: packQueryId, - query: packQuery.query, + query: + dynamicQueryPresent && alertData + ? replaceParamsQuery(packQuery.query, alertData).result + : packQuery.query, ecs_mapping: packQuery.ecs_mapping, version: packQuery.version, platform: packQuery.platform, agents: selectedAgents, }, (value) => !isEmpty(value) - ) - ) - : ecsData - ? await createDynamicQueries(params, ecsData, osqueryContext) + ); + }) + : alertData + ? await createDynamicQueries(params, alertData, osqueryContext) : await createQueries(params, selectedAgents, osqueryContext), }; diff --git a/x-pack/plugins/osquery/server/handlers/action/create_queries.test.ts b/x-pack/plugins/osquery/server/handlers/action/create_queries.test.ts index eabdf998d7b1a..3b88e710fc52b 100644 --- a/x-pack/plugins/osquery/server/handlers/action/create_queries.test.ts +++ b/x-pack/plugins/osquery/server/handlers/action/create_queries.test.ts @@ -6,7 +6,7 @@ */ import { createDynamicQueries, createQueries } from './create_queries'; -import type { Ecs } from '@kbn/core/server'; +import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import type { OsqueryAppContext } from '../../lib/osquery_app_context_services'; describe('create queries', () => { @@ -56,7 +56,7 @@ describe('create queries', () => { process: { pid, }, - } as Ecs, + } as unknown as ParsedTechnicalFields, {} as OsqueryAppContext ); expect(queries[0].query).toBe(`SELECT * FROM processes where pid=${pid};`); @@ -73,7 +73,7 @@ describe('create queries', () => { process: { pid, }, - } as Ecs, + } as unknown as ParsedTechnicalFields, {} as OsqueryAppContext ); expect(queries[0].query).toBe(`SELECT * FROM processes where pid=${pid};`); @@ -83,7 +83,7 @@ describe('create queries', () => { mockedSingleQueryParams, { process: {}, - } as Ecs, + } as unknown as ParsedTechnicalFields, {} as OsqueryAppContext ); expect(queries[0].query).toBe('SELECT * FROM processes where pid={{process.pid}};'); diff --git a/x-pack/plugins/osquery/server/handlers/action/create_queries.ts b/x-pack/plugins/osquery/server/handlers/action/create_queries.ts index 74b954935c1b6..6551b8252e16b 100644 --- a/x-pack/plugins/osquery/server/handlers/action/create_queries.ts +++ b/x-pack/plugins/osquery/server/handlers/action/create_queries.ts @@ -7,9 +7,9 @@ import { isEmpty, map, pickBy } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; -import type { Ecs } from '@kbn/core/server'; import { i18n } from '@kbn/i18n'; +import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import type { OsqueryAppContext } from '../../lib/osquery_app_context_services'; import type { CreateLiveQueryRequestBodySchema } from '../../../common/schemas/routes/live_query'; import { replaceParamsQuery } from '../../../common/utils/replace_params_query'; @@ -53,12 +53,12 @@ export const createQueries = async ( export const createDynamicQueries = async ( params: CreateLiveQueryRequestBodySchema, - alert: Ecs, + alertData: ParsedTechnicalFields, osqueryContext: OsqueryAppContext ) => params.queries?.length ? map(params.queries, ({ query, ...restQuery }) => { - const replacedQuery = replacedQueries(query, alert); + const replacedQuery = replacedQueries(query, alertData); return pickBy( { @@ -76,7 +76,7 @@ export const createDynamicQueries = async ( { action_id: uuidv4(), id: uuidv4(), - ...replacedQueries(params.query, alert), + ...replacedQueries(params.query, alertData), // just for single queries - we need to overwrite the error property error: undefined, saved_query_id: params.saved_query_id, @@ -96,10 +96,10 @@ export const createDynamicQueries = async ( const replacedQueries = ( query: string | undefined, - ecsData?: Ecs + alertData?: ParsedTechnicalFields ): { query: string | undefined; error?: string } => { - if (ecsData && query) { - const { result, skipped } = replaceParamsQuery(query, ecsData); + if (alertData && query) { + const { result, skipped } = replaceParamsQuery(query, alertData); return { query: result, diff --git a/x-pack/plugins/osquery/server/plugin.ts b/x-pack/plugins/osquery/server/plugin.ts index 6b9a6b4d9a71d..b1178285b9f17 100644 --- a/x-pack/plugins/osquery/server/plugin.ts +++ b/x-pack/plugins/osquery/server/plugin.ts @@ -11,13 +11,13 @@ import type { CoreStart, Plugin, Logger, - Ecs, } from '@kbn/core/server'; import { SavedObjectsClient } from '@kbn/core/server'; import type { DataRequestHandlerContext } from '@kbn/data-plugin/server'; import type { DataViewsService } from '@kbn/data-views-plugin/common'; import type { NewPackagePolicy, UpdatePackagePolicy } from '@kbn/fleet-plugin/common'; +import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import { upgradeIntegration } from './utils/upgrade_integration'; import type { PackSavedObjectAttributes } from './common/types'; import { updateGlobalPacksCreateCallback } from './lib/update_global_packs'; @@ -94,8 +94,10 @@ export class OsqueryPlugin implements Plugin - createActionHandler(osqueryContext, params, { ecsData }), + osqueryCreateAction: ( + params: CreateLiveQueryRequestBodySchema, + alertData?: ParsedTechnicalFields + ) => createActionHandler(osqueryContext, params, { alertData }), }; } diff --git a/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts b/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts index 14f31f29125e6..91f3594c5b72a 100644 --- a/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts +++ b/x-pack/plugins/osquery/server/routes/live_query/create_live_query_route.ts @@ -10,7 +10,6 @@ import unified from 'unified'; import markdown from 'remark-parse'; import { some, filter } from 'lodash'; import deepEqual from 'fast-deep-equal'; - import type { ECSMappingOrUndefined } from '@kbn/osquery-io-ts-types'; import { replaceParamsQuery } from '../../../common/utils/replace_params_query'; import { createLiveQueryRequestBodySchema } from '../../../common/schemas/routes/live_query'; @@ -44,15 +43,17 @@ export const createLiveQueryRoute = (router: IRouter, osqueryContext: OsqueryApp (runSavedQueries && (request.body.saved_query_id || request.body.pack_id)) ); + const client = await osqueryContext.service + .getRuleRegistryService() + ?.getRacClientWithRequest(request); + + const alertData = request.body.alert_ids?.length + ? await client?.get({ id: request.body.alert_ids[0] }) + : undefined; + if (isInvalid) { if (request.body.alert_ids?.length) { try { - const client = await osqueryContext.service - .getRuleRegistryService() - ?.getRacClientWithRequest(request); - - const alertData = await client?.get({ id: request.body.alert_ids[0] }); - if (alertData?.['kibana.alert.rule.note']) { const parsedAlertInvestigationGuide = unified() .use([[markdown, {}], OsqueryParser]) @@ -95,7 +96,11 @@ export const createLiveQueryRoute = (router: IRouter, osqueryContext: OsqueryApp const { response: osqueryAction } = await createActionHandler( osqueryContext, request.body, - { soClient, metadata: { currentUser } } + { + soClient, + metadata: { currentUser }, + alertData, + } ); return response.ok({ diff --git a/x-pack/plugins/osquery/server/types.ts b/x-pack/plugins/osquery/server/types.ts index 5a5725bbc019b..d58e39e9ba8cf 100644 --- a/x-pack/plugins/osquery/server/types.ts +++ b/x-pack/plugins/osquery/server/types.ts @@ -11,7 +11,6 @@ import type { PluginSetup as DataPluginSetup, PluginStart as DataPluginStart, } from '@kbn/data-plugin/server'; -import type { Ecs } from '@kbn/ecs'; import type { FleetStartContract } from '@kbn/fleet-plugin/server'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; @@ -23,10 +22,14 @@ import type { } from '@kbn/task-manager-plugin/server'; import type { PluginStart as DataViewsPluginStart } from '@kbn/data-views-plugin/server'; import type { RuleRegistryPluginStartContract } from '@kbn/rule-registry-plugin/server'; +import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import type { CreateLiveQueryRequestBodySchema } from '../common/schemas/routes/live_query'; export interface OsqueryPluginSetup { - osqueryCreateAction: (payload: CreateLiveQueryRequestBodySchema, ecsData?: Ecs) => void; + osqueryCreateAction: ( + payload: CreateLiveQueryRequestBodySchema, + alertData?: ParsedTechnicalFields + ) => void; } // eslint-disable-next-line @typescript-eslint/no-empty-interface diff --git a/x-pack/plugins/osquery/tsconfig.json b/x-pack/plugins/osquery/tsconfig.json index cdacc858b4210..9807641e8b68d 100644 --- a/x-pack/plugins/osquery/tsconfig.json +++ b/x-pack/plugins/osquery/tsconfig.json @@ -65,7 +65,6 @@ "@kbn/securitysolution-es-utils", "@kbn/core-elasticsearch-client-server-mocks", "@kbn/std", - "@kbn/ecs", "@kbn/core-elasticsearch-server", "@kbn/core-saved-objects-api-server", "@kbn/logging", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts index 2640679a7535d..cc04444dec34a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_response_actions/schedule_notification_response_actions.ts @@ -5,29 +5,31 @@ * 2.0. */ -import type { Ecs } from '@kbn/ecs'; import { uniq, reduce, some, each } from 'lodash'; +import { containsDynamicQuery } from '@kbn/osquery-plugin/common/utils/replace_params_query'; +import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import type { RuleResponseAction } from '../../../../common/detection_engine/rule_response_actions/schemas'; import { RESPONSE_ACTION_TYPES } from '../../../../common/detection_engine/rule_response_actions/schemas'; import type { SetupPlugins } from '../../../plugin_contract'; +type Alerts = Array; + interface ScheduleNotificationActions { signals: unknown[]; responseActions: RuleResponseAction[]; } interface AlertsWithAgentType { - alerts: Ecs[]; + alerts: Alerts; agents: string[]; alertIds: string[]; } -const CONTAINS_DYNAMIC_PARAMETER_REGEX = /\{{([^}]+)\}}/g; // when there are 2 opening and 2 closing curly brackets (including brackets) export const scheduleNotificationResponseActions = ( { signals, responseActions }: ScheduleNotificationActions, osqueryCreateAction?: SetupPlugins['osquery']['osqueryCreateAction'] ) => { - const filteredAlerts = (signals as Ecs[]).filter((alert) => alert.agent?.id); + const filteredAlerts = (signals as Alerts).filter((alert) => alert.agent?.id); const { alerts, agents, alertIds }: AlertsWithAgentType = reduce( filteredAlerts, @@ -51,9 +53,10 @@ export const scheduleNotificationResponseActions = ( const temporaryQueries = responseAction.params.queries?.length ? responseAction.params.queries : [{ query: responseAction.params.query }]; - const containsDynamicQueries = some(temporaryQueries, (query) => { - return query.query ? new RegExp(CONTAINS_DYNAMIC_PARAMETER_REGEX).test(query.query) : false; - }); + const containsDynamicQueries = some( + temporaryQueries, + (query) => query.query && containsDynamicQuery(query.query) + ); const { savedQueryId, packId, queries, ecsMapping, ...rest } = responseAction.params; if (!containsDynamicQueries) { diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index 9d312e57f98af..daa763a72f377 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -130,7 +130,6 @@ "@kbn/core-status-common-internal", "@kbn/repo-info", "@kbn/storybook", - "@kbn/ecs", "@kbn/cypress-config", "@kbn/controls-plugin", "@kbn/shared-ux-utility", From 587816830afdb70f66ed058bb009f942c0bab3ea Mon Sep 17 00:00:00 2001 From: Jeramy Soucy Date: Tue, 14 Feb 2023 10:22:26 -0500 Subject: [PATCH 183/203] Upgrades joi to 17.7.1 (#150953) Upgrades joi to version 17.7.1 --- package.json | 2 +- yarn.lock | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index ea120b03ecc69..769c09752fcd6 100644 --- a/package.json +++ b/package.json @@ -791,7 +791,7 @@ "io-ts": "^2.0.5", "ipaddr.js": "2.0.0", "isbinaryfile": "4.0.2", - "joi": "^17.4.0", + "joi": "^17.7.1", "jquery": "^3.5.0", "js-levenshtein": "^1.1.6", "js-search": "^1.4.3", diff --git a/yarn.lock b/yarn.lock index 813b70a2205a8..00d1f3210c11d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6377,17 +6377,17 @@ agentkeepalive "^4.1.3" lodash "^4.17.21" -"@sideway/address@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.0.tgz#0b301ada10ac4e0e3fa525c90615e0b61a72b78d" - integrity sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA== +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== dependencies: "@hapi/hoek" "^9.0.0" -"@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== +"@sideway/formula@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== "@sideway/pinpoint@^2.0.0": version "2.0.0" @@ -19241,15 +19241,15 @@ jest@^29.3.1: import-local "^3.0.2" jest-cli "^29.3.1" -joi@^17.3.0, joi@^17.4.0: - version "17.4.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.0.tgz#b5c2277c8519e016316e49ababd41a1908d9ef20" - integrity sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg== +joi@^17.3.0, joi@^17.7.1: + version "17.7.1" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.1.tgz#854fc85c7fa3cfc47c91124d30bffdbb58e06cec" + integrity sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.0" - "@sideway/formula" "^3.0.0" + "@sideway/address" "^4.1.3" + "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" jpeg-js@0.0.4: From 7fe81548b3272b35d63b498e17188b9c56b1022a Mon Sep 17 00:00:00 2001 From: "Quynh Nguyen (Quinn)" <43350163+qn895@users.noreply.github.com> Date: Tue, 14 Feb 2023 11:09:33 -0600 Subject: [PATCH 184/203] [ML] Fix sampling probability when switching between automatic and manual (#150389) --- .../document_count_content.tsx | 107 +++++++---------- .../random_sampler_range_slider.tsx | 112 ++++++++++++++++++ .../index_data_visualizer_view.tsx | 50 +++++++- .../constants/random_sampler.ts | 10 +- .../index_data_visualizer/types/storage.ts | 2 +- .../index_data_visualizer_random_sampler.ts | 3 +- .../ml/data_visualizer_index_based.ts | 6 +- 7 files changed, 206 insertions(+), 84 deletions(-) create mode 100644 x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/random_sampler_range_slider.tsx diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx index 4e3ed74c4470e..cb4f55b49cb41 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/document_count_content.tsx @@ -15,18 +15,14 @@ import { EuiPanel, EuiSpacer, EuiCallOut, - EuiRange, EuiSelect, EuiFormRow, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { debounce, sortedIndex } from 'lodash'; import { FormattedMessage } from '@kbn/i18n-react'; import { isDefined } from '@kbn/ml-is-defined'; import type { DocumentCountChartPoint } from './document_count_chart'; import { - RANDOM_SAMPLER_STEP, - RANDOM_SAMPLER_PROBABILITIES, RandomSamplerOption, RANDOM_SAMPLER_SELECT_OPTIONS, RANDOM_SAMPLER_OPTION, @@ -34,17 +30,43 @@ import { import { TotalCountHeader } from './total_count_header'; import type { DocumentCountStats } from '../../../../../common/types/field_stats'; import { DocumentCountChart } from './document_count_chart'; +import { RandomSamplerRangeSlider } from './random_sampler_range_slider'; export interface Props { documentCountStats?: DocumentCountStats; totalCount: number; samplingProbability?: number | null; - setSamplingProbability?: (value: number) => void; + setSamplingProbability?: (value: number | null) => void; randomSamplerPreference?: RandomSamplerOption; setRandomSamplerPreference: (value: RandomSamplerOption) => void; loading: boolean; } +const ProbabilityUsedMessage = ({ samplingProbability }: Pick) => { + return isDefined(samplingProbability) ? ( +
    + + + +
    + ) : null; +}; + +const CalculatingProbabilityMessage = ( +
    + + + +
    +); + export const DocumentCountContent: FC = ({ documentCountStats, totalCount, @@ -64,24 +86,6 @@ export const DocumentCountContent: FC = ({ setShowSamplingOptionsPopover(false); }, [setShowSamplingOptionsPopover]); - // eslint-disable-next-line react-hooks/exhaustive-deps - const updateSamplingProbability = useCallback( - debounce((newProbability: number) => { - if (setSamplingProbability) { - const idx = sortedIndex(RANDOM_SAMPLER_PROBABILITIES, newProbability); - const closestPrev = RANDOM_SAMPLER_PROBABILITIES[idx - 1]; - const closestNext = RANDOM_SAMPLER_PROBABILITIES[idx]; - const closestProbability = - Math.abs(closestPrev - newProbability) < Math.abs(closestNext - newProbability) - ? closestPrev - : closestNext; - - setSamplingProbability(closestProbability / 100); - } - }, 100), - [setSamplingProbability] - ); - const calloutInfoMessage = useMemo(() => { switch (randomSamplerPreference) { case RANDOM_SAMPLER_OPTION.OFF: @@ -126,19 +130,6 @@ export const DocumentCountContent: FC = ({ const approximate = documentCountStats.randomlySampled === true; - const ProbabilityUsed = - randomSamplerPreference !== RANDOM_SAMPLER_OPTION.OFF && isDefined(samplingProbability) ? ( -
    - - - -
    - ) : null; - return ( <> @@ -195,37 +186,19 @@ export const DocumentCountContent: FC = ({ {randomSamplerPreference === RANDOM_SAMPLER_OPTION.ON_MANUAL ? ( - - - - ({ - value: d, - label: d === 0.001 || d >= 5 ? `${d}%` : '', - }))} - onChange={(e) => updateSamplingProbability(Number(e.currentTarget.value))} - step={RANDOM_SAMPLER_STEP} - data-test-subj="dvRandomSamplerProbabilityRange" - /> - - - ) : ( - ProbabilityUsed - )} + + ) : null} + + {randomSamplerPreference === RANDOM_SAMPLER_OPTION.ON_AUTOMATIC ? ( + loading ? ( + CalculatingProbabilityMessage + ) : ( + + ) + ) : null} diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/random_sampler_range_slider.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/random_sampler_range_slider.tsx new file mode 100644 index 0000000000000..6b689e08273f9 --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/common/components/document_count_content/random_sampler_range_slider.tsx @@ -0,0 +1,112 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiButton, EuiFlexItem, EuiFormRow, EuiRange, EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { isDefined } from '@kbn/ml-is-defined'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React, { useState } from 'react'; +import { roundToDecimalPlace } from '../utils'; +import { + MIN_SAMPLER_PROBABILITY, + RANDOM_SAMPLER_PROBABILITIES, + RANDOM_SAMPLER_STEP, +} from '../../../index_data_visualizer/constants/random_sampler'; + +export const RandomSamplerRangeSlider = ({ + samplingProbability, + setSamplingProbability, +}: { + samplingProbability?: number | null; + setSamplingProbability?: (value: number | null) => void; +}) => { + // Keep track of the input in sampling probability slider when mode is on - manual + // before 'Apply' is clicked + const [samplingProbabilityInput, setSamplingProbabilityInput] = useState(samplingProbability); + + const isInvalidSamplingProbabilityInput = + !isDefined(samplingProbabilityInput) || + isNaN(samplingProbabilityInput) || + samplingProbabilityInput < MIN_SAMPLER_PROBABILITY || + samplingProbabilityInput > 0.5; + + const inputValue = (samplingProbabilityInput ?? MIN_SAMPLER_PROBABILITY) * 100; + + return ( + + + + = 1 + ? roundToDecimalPlace(inputValue, 0) + : roundToDecimalPlace(inputValue, 3) + } + ticks={RANDOM_SAMPLER_PROBABILITIES.map((d) => ({ + value: d, + label: d === 0.001 || d >= 5 ? `${d}` : '', + }))} + isInvalid={isInvalidSamplingProbabilityInput} + onChange={(e) => { + const value = parseFloat((e.target as HTMLInputElement).value); + const prevValue = samplingProbabilityInput ? samplingProbabilityInput * 100 : value; + + if (value > 0 && value <= 1) { + setSamplingProbabilityInput(value / 100); + } else { + // Because the incremental step is very small (0.0001), + // everytime user clicks the ^/∨ in the numerical input + // we need to make sure it rounds up or down to the next whole number + const nearestInt = value > prevValue ? Math.ceil(value) : Math.floor(value); + setSamplingProbabilityInput(nearestInt / 100); + } + }} + step={RANDOM_SAMPLER_STEP} + data-test-subj="dvRandomSamplerProbabilityRange" + append={ + { + if (setSamplingProbability && isDefined(samplingProbabilityInput)) { + setSamplingProbability(samplingProbabilityInput); + } + }} + > + + + } + /> + + + ); +}; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx index 1508683fd1a43..18695703fb87d 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx @@ -41,6 +41,7 @@ import { useCurrentEuiTheme } from '../../../common/hooks/use_current_eui_theme' import { DV_FROZEN_TIER_PREFERENCE, DV_RANDOM_SAMPLER_PREFERENCE, + DV_RANDOM_SAMPLER_P_VALUE, type DVKey, type DVStorageMapped, } from '../../types/storage'; @@ -71,7 +72,11 @@ import { DataVisualizerDataViewManagement } from '../data_view_management'; import { GetAdditionalLinks } from '../../../common/components/results_links'; import { useDataVisualizerGridData } from '../../hooks/use_data_visualizer_grid_data'; import { DataVisualizerGridInput } from '../../embeddables/grid_embeddable/grid_embeddable'; -import { RANDOM_SAMPLER_OPTION } from '../../constants/random_sampler'; +import { + MIN_SAMPLER_PROBABILITY, + RANDOM_SAMPLER_OPTION, + RandomSamplerOption, +} from '../../constants/random_sampler'; interface DataVisualizerPageState { overallStats: OverallStats; @@ -143,6 +148,11 @@ export const IndexDataVisualizerView: FC = (dataVi DVStorageMapped >(DV_RANDOM_SAMPLER_PREFERENCE, RANDOM_SAMPLER_OPTION.ON_AUTOMATIC); + const [savedRandomSamplerProbability, saveRandomSamplerProbability] = useStorage< + DVKey, + DVStorageMapped + >(DV_RANDOM_SAMPLER_P_VALUE, MIN_SAMPLER_PROBABILITY); + const [frozenDataPreference, setFrozenDataPreference] = useStorage< DVKey, DVStorageMapped @@ -156,6 +166,7 @@ export const IndexDataVisualizerView: FC = (dataVi () => getDefaultDataVisualizerListState({ rndSamplerPref: savedRandomSamplerPreference, + probability: savedRandomSamplerProbability, }), // We just need to load the saved preference when the page is first loaded // eslint-disable-next-line react-hooks/exhaustive-deps @@ -316,9 +327,38 @@ export const IndexDataVisualizerView: FC = (dataVi ] ); - const setSamplingProbability = (value: number | null) => { - setDataVisualizerListState({ ...dataVisualizerListState, probability: value }); - }; + const setSamplingProbability = useCallback( + (value: number | null) => { + if (savedRandomSamplerPreference === RANDOM_SAMPLER_OPTION.ON_MANUAL && value !== null) { + saveRandomSamplerProbability(value); + } + setDataVisualizerListState({ ...dataVisualizerListState, probability: value }); + }, + [ + dataVisualizerListState, + saveRandomSamplerProbability, + savedRandomSamplerPreference, + setDataVisualizerListState, + ] + ); + + const setRandomSamplerPreference = useCallback( + (nextPref: RandomSamplerOption) => { + if (nextPref === RANDOM_SAMPLER_OPTION.ON_MANUAL) { + // By default, when switching to manual, restore previously chosen probability + // else, default to 0.001% + setSamplingProbability( + savedRandomSamplerProbability && + savedRandomSamplerProbability > 0 && + savedRandomSamplerProbability <= 0.5 + ? savedRandomSamplerProbability + : MIN_SAMPLER_PROBABILITY + ); + } + saveRandomSamplerPreference(nextPref); + }, + [savedRandomSamplerProbability, setSamplingProbability, saveRandomSamplerPreference] + ); useEffect( function clearFiltersOnLeave() { @@ -565,7 +605,7 @@ export const IndexDataVisualizerView: FC = (dataVi } loading={overallStatsProgress.loaded < 100} randomSamplerPreference={savedRandomSamplerPreference} - setRandomSamplerPreference={saveRandomSamplerPreference} + setRandomSamplerPreference={setRandomSamplerPreference} /> diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts index 310ccde5f9e29..f1cfdd3d2bca8 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/constants/random_sampler.ts @@ -8,13 +8,11 @@ import { i18n } from '@kbn/i18n'; export const RANDOM_SAMPLER_PROBABILITIES = [ - 0.5, 0.25, 0.1, 0.05, 0.025, 0.01, 0.005, 0.0025, 0.001, 0.0005, 0.00025, 0.0001, 0.00005, - 0.00001, -] - .reverse() - .map((n) => n * 100); + 0.00001, 0.00005, 0.0001, 0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, +].map((n) => n * 100); -export const RANDOM_SAMPLER_STEP = 0.00001 * 100; +export const MIN_SAMPLER_PROBABILITY = 0.00001; +export const RANDOM_SAMPLER_STEP = MIN_SAMPLER_PROBABILITY * 100; export const RANDOM_SAMPLER_OPTION = { ON_AUTOMATIC: 'on_automatic', diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/types/storage.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/types/storage.ts index cbafcfd63c633..372fa2a738a53 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/types/storage.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/types/storage.ts @@ -16,7 +16,7 @@ export const DV_RANDOM_SAMPLER_P_VALUE = 'dataVisualizer.randomSamplerPValue'; export type DV = Partial<{ [DV_FROZEN_TIER_PREFERENCE]: FrozenTierPreference; [DV_RANDOM_SAMPLER_PREFERENCE]: RandomSamplerOption; - [DV_RANDOM_SAMPLER_P_VALUE]: number; + [DV_RANDOM_SAMPLER_P_VALUE]: null | number; }> | null; export type DVKey = keyof Exclude; diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_random_sampler.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_random_sampler.ts index 7df4e9c18eee7..ce74bbfb8884a 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_random_sampler.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_random_sampler.ts @@ -71,8 +71,7 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { await goToSourceForIndexBasedDataVisualizer('ft_module_sample_logs'); await ml.dataVisualizerIndexBased.assertRandomSamplingOption( - 'dvRandomSamplerOptionOnManual', - 50 + 'dvRandomSamplerOptionOnManual' ); }); }); diff --git a/x-pack/test/functional/services/ml/data_visualizer_index_based.ts b/x-pack/test/functional/services/ml/data_visualizer_index_based.ts index e46108373d450..c15569bb262ac 100644 --- a/x-pack/test/functional/services/ml/data_visualizer_index_based.ts +++ b/x-pack/test/functional/services/ml/data_visualizer_index_based.ts @@ -258,7 +258,7 @@ export function MachineLearningDataVisualizerIndexBasedProvider({ if (expectedOption === 'dvRandomSamplerOptionOff') { await testSubjects.existOrFail('dvRandomSamplerOptionOff', { timeout: 1000 }); await testSubjects.missingOrFail('dvRandomSamplerProbabilityRange', { timeout: 1000 }); - await testSubjects.missingOrFail('dvRandomSamplerAutomaticProbabilityMsg', { + await testSubjects.missingOrFail('dvRandomSamplerProbabilityUsedMsg', { timeout: 1000, }); } @@ -280,13 +280,13 @@ export function MachineLearningDataVisualizerIndexBasedProvider({ if (expectedOption === 'dvRandomSamplerOptionOnAutomatic') { await testSubjects.existOrFail('dvRandomSamplerOptionOnAutomatic', { timeout: 1000 }); - await testSubjects.existOrFail('dvRandomSamplerAutomaticProbabilityMsg', { + await testSubjects.existOrFail('dvRandomSamplerProbabilityUsedMsg', { timeout: 1000, }); if (expectedProbability !== undefined) { const probabilityText = await testSubjects.getVisibleText( - 'dvRandomSamplerAutomaticProbabilityMsg' + 'dvRandomSamplerProbabilityUsedMsg' ); expect(probabilityText).to.contain( `${expectedProbability}`, From ff312c9f0442352a11e1ff373ee78632a6c58afd Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 14 Feb 2023 09:14:05 -0800 Subject: [PATCH 185/203] [DOCS] Clarify alerting security (#150653) --- docs/user/alerting/alerting-setup.asciidoc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/user/alerting/alerting-setup.asciidoc b/docs/user/alerting/alerting-setup.asciidoc index 36c8b46e7b801..5217e80ed2c09 100644 --- a/docs/user/alerting/alerting-setup.asciidoc +++ b/docs/user/alerting/alerting-setup.asciidoc @@ -1,4 +1,3 @@ -[role="xpack"] [[alerting-setup]] == Alerting set up ++++ @@ -17,10 +16,10 @@ If you are using an *on-premises* {stack} deployment: <> setting. * For emails to have a footer with a link back to {kib}, set the -<> configuration setting. +<> configuration setting. If you are using an *on-premises* {stack} deployment with -<>: +<>: * If you are unable to access {kib} {alert-features}, ensure that you have not {ref}/security-settings.html#api-key-service-settings[explicitly disabled API keys]. @@ -47,10 +46,10 @@ For more information on the scalability of {alert-features}, go to If you want to use the {alert-features} in a {kib} app, you must have the appropriate feature privileges. For example, to create rules in *{stack-manage-app} > {rules-ui}*, you must have `all` privileges for the -*Management > Stack Rules* feature. To attach actions to the rule, you must also -have `read` privileges for the *{connectors-feature}* feature. For more -information on configuring roles that provide access to features, go to -<>. +*Management > {stack-rules-feature}* feature. To add rule actions and test +connectors, you must also have `read` privileges for the *{connectors-feature}* +feature. For more information on configuring roles that provide access to +features, go to <>. For details about the prerequisites for each API, refer to <>. From f5eab68998c54f31a62deb141f2490a1772d8586 Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Tue, 14 Feb 2023 11:21:58 -0600 Subject: [PATCH 186/203] [Enterprise Search] fix: search experiences plugin name (#150945) ## Summary Updated the Search experiences navigation shortcut to be "Search Experiences" instead of "Enterprise Search" ### Screenshot ![image](https://user-images.githubusercontent.com/1972968/218199866-6a78a1e8-861f-4ca7-9c8f-6e514642ec52.png) --- x-pack/plugins/enterprise_search/common/constants.ts | 4 ++-- .../search_experiences/components/layout/page_template.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/enterprise_search/common/constants.ts b/x-pack/plugins/enterprise_search/common/constants.ts index 39d0f51b067b8..091dc88b5a689 100644 --- a/x-pack/plugins/enterprise_search/common/constants.ts +++ b/x-pack/plugins/enterprise_search/common/constants.ts @@ -100,10 +100,10 @@ export const WORKPLACE_SEARCH_PLUGIN = { export const SEARCH_EXPERIENCES_PLUGIN = { ID: 'searchExperiences', NAME: i18n.translate('xpack.enterpriseSearch.searchExperiences.productName', { - defaultMessage: 'Enterprise Search', + defaultMessage: 'Search Experiences', }), NAV_TITLE: i18n.translate('xpack.enterpriseSearch.searchExperiences.navTitle', { - defaultMessage: 'Search experiences', + defaultMessage: 'Search Experiences', }), DESCRIPTION: i18n.translate('xpack.enterpriseSearch.searchExperiences.productDescription', { defaultMessage: 'Build an intuitive, engaging search experience without reinventing the wheel.', diff --git a/x-pack/plugins/enterprise_search/public/applications/search_experiences/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/search_experiences/components/layout/page_template.tsx index 5c4d1958d0c38..704f9d06f3e19 100644 --- a/x-pack/plugins/enterprise_search/public/applications/search_experiences/components/layout/page_template.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/search_experiences/components/layout/page_template.tsx @@ -7,7 +7,7 @@ import React from 'react'; -import { SEARCH_EXPERIENCES_PLUGIN } from '../../../../../common/constants'; +import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../../../../common/constants'; import { SetSearchExperiencesChrome } from '../../../shared/kibana_chrome'; import { EnterpriseSearchPageTemplateWrapper, PageTemplateProps } from '../../../shared/layout'; import { useEnterpriseSearchNav } from '../../../shared/layout'; @@ -23,7 +23,7 @@ export const EnterpriseSearchSearchExperiencesPageTemplate: React.FC} From 1733b3a87125c3d97eee8813bddcb3f30f39f44e Mon Sep 17 00:00:00 2001 From: Philippe Oberti Date: Tue, 14 Feb 2023 11:31:55 -0600 Subject: [PATCH 187/203] [TIP] enable Cypress screenshot upload on CI for failing tests (#151166) --- .buildkite/pipelines/pull_request/threat_intelligence.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.buildkite/pipelines/pull_request/threat_intelligence.yml b/.buildkite/pipelines/pull_request/threat_intelligence.yml index 5a4b3b59588f1..258c04293f65b 100644 --- a/.buildkite/pipelines/pull_request/threat_intelligence.yml +++ b/.buildkite/pipelines/pull_request/threat_intelligence.yml @@ -12,3 +12,5 @@ steps: limit: 3 - exit_status: '*' limit: 1 + artifact_paths: + - "target/kibana-threat-intelligence/**/*" From fb1a8ce66d1e4814cbc04658f42c4c4cbf747877 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 14 Feb 2023 17:34:39 +0000 Subject: [PATCH 188/203] [Fleet] Input packages: Use policy template name for default dataset (#151140) ## Summary Closes #151137 We were using "generic" as the dataset name for all input packages which was a bad UX. I have moved to using the policy template name e.g for jolokia we now create metrics-jolokia datastream by default instead of metrics-generic Screenshot 2023-02-14 at 14 25 18 --- .../plugins/fleet/common/services/policy_template.ts | 12 +++++++++--- .../apis/package_policy/create.ts | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/fleet/common/services/policy_template.ts b/x-pack/plugins/fleet/common/services/policy_template.ts index 4265767a9be25..c8fa687123fc6 100644 --- a/x-pack/plugins/fleet/common/services/policy_template.ts +++ b/x-pack/plugins/fleet/common/services/policy_template.ts @@ -79,7 +79,7 @@ export const getNormalizedDataStreams = ( streams: [ { input: policyTemplate.input, - vars: addDatasetVarIfNotPresent(policyTemplate.vars), + vars: addDatasetVarIfNotPresent(policyTemplate.vars, policyTemplate.name), template_path: policyTemplate.template_path, title: policyTemplate.title, description: policyTemplate.title, @@ -94,7 +94,10 @@ export const getNormalizedDataStreams = ( // Input only packages must provide a dataset name in order to differentiate their data streams // here we add the dataset var if it is not defined in the package already. -const addDatasetVarIfNotPresent = (vars?: RegistryVarsEntry[]): RegistryVarsEntry[] => { +const addDatasetVarIfNotPresent = ( + vars?: RegistryVarsEntry[], + datasetName?: string +): RegistryVarsEntry[] => { const newVars = vars ?? []; const isDatasetAlreadyAdded = newVars.find( @@ -104,7 +107,10 @@ const addDatasetVarIfNotPresent = (vars?: RegistryVarsEntry[]): RegistryVarsEntr if (isDatasetAlreadyAdded) { return newVars; } else { - return [...newVars, DATA_STREAM_DATASET_VAR]; + return [ + ...newVars, + { ...DATA_STREAM_DATASET_VAR, ...(datasetName && { default: datasetName }) }, + ]; } }; diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts index 1783a1fc53d09..7def6a1801bfd 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/create.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/create.ts @@ -447,7 +447,7 @@ export default function (providerContext: FtrProviderContext) { }); describe('input only packages', () => { - it('should return 400 if dataset not provided for input only pkg', async function () { + it('should default dataset if not provided for input only pkg', async function () { await supertest .post(`/api/fleet/package_policies`) .set('kbn-xsrf', 'xxxx') @@ -476,7 +476,7 @@ export default function (providerContext: FtrProviderContext) { }, }, }) - .expect(400); + .expect(200); }); it('should successfully create an input only package policy with all required vars', async function () { await supertest From a608af64257ae3ad221dec26f2ae6c03391c2836 Mon Sep 17 00:00:00 2001 From: Zacqary Adam Xeper Date: Tue, 14 Feb 2023 11:38:41 -0600 Subject: [PATCH 189/203] [RAM] Cover rewriteRule in unit/integration tests (#150817) ## Summary Closes #149642 - Adds a unit test for `rewriteRule` - Adds actions to the integration tests for the `_find` API ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../server/routes/lib/rewrite_rule.test.ts | 88 +++++++++++++++++++ .../group1/tests/alerting/find.ts | 50 +++++++++-- .../spaces_only/tests/alerting/group1/find.ts | 48 +++++++++- 3 files changed, 176 insertions(+), 10 deletions(-) create mode 100644 x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.ts diff --git a/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.ts b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.ts new file mode 100644 index 0000000000000..b4d1962931218 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/lib/rewrite_rule.test.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 { rewriteRule } from './rewrite_rule'; +import { RuleTypeParams, SanitizedRule } from '../../types'; +import { isPlainObject } from 'lodash'; + +const DATE_2020 = new Date('1/1/2020'); + +const sampleRule: SanitizedRule & { activeSnoozes?: string[] } = { + id: 'aaaa', + name: 'Sample Rule', + enabled: true, + tags: [], + consumer: 'xxxx', + schedule: { interval: '1m' }, + params: {}, + alertTypeId: 'abc123', + createdBy: 'user', + updatedBy: 'user', + createdAt: DATE_2020, + updatedAt: DATE_2020, + apiKeyOwner: 'owner', + notifyWhen: null, + muteAll: false, + mutedInstanceIds: ['abc', '123'], + executionStatus: { + status: 'ok', + lastExecutionDate: DATE_2020, + lastDuration: 1000, + }, + actions: [ + { + group: 'default', + id: 'aaa', + actionTypeId: 'bbb', + params: {}, + frequency: { + summary: false, + notifyWhen: 'onThrottleInterval', + throttle: '1m', + }, + }, + ], + scheduledTaskId: 'xyz456', + snoozeSchedule: [], + isSnoozedUntil: null, + activeSnoozes: [], + lastRun: { + outcome: 'succeeded', + outcomeMsg: null, + alertsCount: { + active: 1, + new: 1, + recovered: 1, + ignored: 1, + }, + }, + nextRun: DATE_2020, +}; + +describe('rewriteRule', () => { + it('should not camelCase any property names', () => { + const rewritten = rewriteRule(sampleRule); + for (const [key, val] of Object.entries(rewritten)) { + expect(key.toLowerCase()).toEqual(key); + if (isPlainObject(val)) { + for (const keyO of Object.keys(rewritten)) { + expect(keyO.toLowerCase()).toEqual(keyO); + } + } + } + }); + it('should rewrite actions correctly', () => { + const rewritten = rewriteRule(sampleRule); + for (const action of rewritten.actions) { + expect(Object.keys(action)).toEqual( + expect.arrayContaining(['group', 'id', 'connector_type_id', 'params', 'frequency']) + ); + expect(Object.keys(action.frequency!)).toEqual( + expect.arrayContaining(['summary', 'notify_when', 'throttle']) + ); + } + }); +}); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts index b4fbd37d5a1e8..d35314176d657 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts @@ -27,13 +27,39 @@ const findTestUtils = ( const { user, space } = scenario; describe(scenario.id, () => { it('should handle find alert request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(space.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'MY action', + connector_type_id: 'test.noop', + config: {}, + secrets: {}, + }) + .expect(200); + const { body: createdAlert } = await supertest .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) + .send( + getTestRuleData({ + actions: [ + { + group: 'default', + id: createdAction.id, + params: {}, + frequency: { + summary: false, + notify_when: 'onThrottleInterval', + throttle: '1m', + }, + }, + ], + notify_when: undefined, + throttle: undefined, + }) + ) .expect(200); - objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); - const response = await supertestWithoutAuth .get( `${getUrlPrefix(space.id)}/${ @@ -73,14 +99,26 @@ const findTestUtils = ( consumer: 'alertsFixture', schedule: { interval: '1m' }, enabled: true, - actions: [], + actions: [ + { + group: 'default', + id: createdAction.id, + connector_type_id: 'test.noop', + params: {}, + frequency: { + summary: false, + notify_when: 'onThrottleInterval', + throttle: '1m', + }, + }, + ], params: {}, created_by: 'elastic', scheduled_task_id: match.scheduled_task_id, created_at: match.created_at, updated_at: match.updated_at, - throttle: '1m', - notify_when: 'onThrottleInterval', + throttle: null, + notify_when: null, updated_by: 'elastic', api_key_owner: 'elastic', mute_all: false, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts index 30b3643466f42..975ed2a3913c6 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts @@ -34,10 +34,38 @@ const findTestUtils = ( describe(describeType, () => { afterEach(() => objectRemover.removeAll()); it('should handle find alert request appropriately', async () => { + const { body: createdAction } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'MY action', + connector_type_id: 'test.noop', + config: {}, + secrets: {}, + }) + .expect(200); + const { body: createdAlert } = await supertest .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) + .send( + getTestRuleData({ + actions: [ + { + group: 'default', + id: createdAction.id, + params: {}, + frequency: { + summary: false, + notify_when: 'onThrottleInterval', + throttle: '1m', + }, + }, + ], + notify_when: undefined, + throttle: undefined, + }) + ) .expect(200); objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); @@ -63,14 +91,26 @@ const findTestUtils = ( consumer: 'alertsFixture', schedule: { interval: '1m' }, enabled: true, - actions: [], + actions: [ + { + group: 'default', + id: createdAction.id, + connector_type_id: 'test.noop', + params: {}, + frequency: { + summary: false, + notify_when: 'onThrottleInterval', + throttle: '1m', + }, + }, + ], params: {}, created_by: null, api_key_owner: null, scheduled_task_id: match.scheduled_task_id, updated_by: null, - throttle: '1m', - notify_when: 'onThrottleInterval', + throttle: null, + notify_when: null, mute_all: false, muted_alert_ids: [], created_at: match.created_at, From 1fb3ef499fdc9e999904b04eae6a2bdad76228b3 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 14 Feb 2023 10:57:42 -0700 Subject: [PATCH 190/203] [ML] Anomaly detection wizards: adds functional test for geo wizard (#150942) ## Summary Adds functional tests for the geo wizard in anomaly detection [Flaky test runner build](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1913) ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Robert Oskamp --- .../components/split_field/split_field.tsx | 2 +- .../apps/ml/anomaly_detection_jobs/geo_job.ts | 354 ++++++++++++++++++ .../apps/ml/anomaly_detection_jobs/index.ts | 1 + x-pack/test/functional/services/ml/index.ts | 3 + .../services/ml/job_type_selection.ts | 9 + .../functional/services/ml/job_wizard_geo.ts | 52 +++ .../services/ml/job_wizard_multi_metric.ts | 8 +- 7 files changed, 424 insertions(+), 5 deletions(-) create mode 100644 x-pack/test/functional/apps/ml/anomaly_detection_jobs/geo_job.ts create mode 100644 x-pack/test/functional/services/ml/job_wizard_geo.ts diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/split_field/split_field.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/split_field/split_field.tsx index 3eb1bd6ea840b..db560c70bf0db 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/split_field/split_field.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/split_field/split_field.tsx @@ -62,7 +62,7 @@ export const SplitFieldSelector: FC = () => { changeHandler={setSplitField} selectedField={splitField} isClearable={true} - testSubject="mlMultiMetricSplitFieldSelect" + testSubject="mlSplitFieldSelect" /> ); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_jobs/geo_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/geo_job.ts new file mode 100644 index 0000000000000..daed44cce85fa --- /dev/null +++ b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/geo_job.ts @@ -0,0 +1,354 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + const jobId = `ec_geo_1_${Date.now()}`; + const jobIdClone = `${jobId}_clone`; + const jobDescription = 'Create geo job based on the ecommerce sample dataset with 15m bucketspan'; + const jobGroups = ['automated', 'ecommerce', 'geo']; + const jobGroupsClone = [...jobGroups, 'clone']; + const geoField = 'geoip.location'; + const splitField = 'customer_gender'; + const detectors = [ + { + identifier: 'Lat long(geoip.location)', + frontCardTitle: "Men's Clothing", + function: 'lat_long', + field_name: geoField, + numberOfBackCards: 5, + splitField, + }, + ]; + const bucketSpan = '15m'; + const memoryLimit = '8mb'; + + function getExpectedRow(expectedJobId: string, expectedJobGroups: string[]) { + return { + id: expectedJobId, + description: jobDescription, + jobGroups: [...new Set(expectedJobGroups)].sort(), + recordCount: '4,675', + memoryStatus: 'ok', + jobState: 'closed', + datafeedState: 'stopped', + latestTimestamp: '2019-07-12 23:45:36', + }; + } + + function getExpectedCounts(expectedJobId: string) { + return { + job_id: expectedJobId, + processed_record_count: '4,675', + processed_field_count: '9,350', + input_bytes: '504.1 KB', + input_field_count: '9,350', + invalid_date_count: '0', + missing_field_count: '0', + out_of_order_timestamp_count: '0', + empty_bucket_count: '492', + sparse_bucket_count: '0', + bucket_count: '2,975', + earliest_record_timestamp: '2019-06-12 00:04:19', + latest_record_timestamp: '2019-07-12 23:45:36', + input_record_count: '4,675', + latest_bucket_timestamp: '2019-07-12 23:45:00', + }; + } + + function getExpectedModelSizeStats(expectedJobId: string) { + return { + job_id: expectedJobId, + result_type: 'model_size_stats', + model_bytes_exceeded: '0.0 B', + total_by_field_count: '4', + total_over_field_count: '0', + total_partition_field_count: '3', + bucket_allocation_failures_count: '0', + memory_status: 'ok', + timestamp: '2019-07-12 23:30:00', + }; + } + + const calendarId = `wizard-test-calendar_${Date.now()}`; + + describe('geo', function () { + this.tags(['ml']); + before(async () => { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ecommerce'); + await ml.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date'); + await ml.testResources.setKibanaTimeZoneToUTC(); + + await ml.api.createCalendar(calendarId); + await ml.securityUI.loginAsMlPowerUser(); + }); + + after(async () => { + await ml.api.cleanMlIndices(); + await ml.testResources.deleteIndexPatternByTitle('ft_ecommerce'); + }); + + it('job creation loads the geo wizard for the source data', async () => { + await ml.testExecution.logTestStep('job creation loads the job management page'); + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.testExecution.logTestStep('job creation loads the new job source selection page'); + await ml.jobManagement.navigateToNewJobSourceSelection(); + + await ml.testExecution.logTestStep('job creation loads the job type selection page'); + await ml.jobSourceSelection.selectSourceForAnomalyDetectionJob('ft_ecommerce'); + + await ml.testExecution.logTestStep('job creation loads the geo job wizard page'); + await ml.jobTypeSelection.selectGeoJob(); + }); + + it('job creation navigates through the geo wizard and sets all needed fields', async () => { + await ml.testExecution.logTestStep('job creation displays the time range step'); + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + + await ml.testExecution.logTestStep('job creation sets the time range'); + await ml.jobWizardCommon.clickUseFullDataButton( + 'Jun 12, 2019 @ 00:04:19.000', + 'Jul 12, 2019 @ 23:45:36.000' + ); + + await ml.testExecution.logTestStep('job creation displays the event rate chart'); + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + + await ml.testExecution.logTestStep('job creation displays the pick fields step'); + await ml.jobWizardCommon.advanceToPickFieldsSection(); + + await ml.testExecution.logTestStep('job creation selects the geo field'); + await ml.jobWizardGeo.assertGeoFieldInputExists(); + await ml.jobWizardGeo.selectGeoField(geoField); + + await ml.testExecution.logTestStep('job creation displays detector preview'); + + await ml.jobWizardGeo.assertDetectorPreviewExists(detectors[0].identifier); + + await ml.testExecution.logTestStep( + 'job creation inputs the split field and displays split cards' + ); + + await ml.jobWizardMultiMetric.assertSplitFieldInputExists(); + await ml.jobWizardMultiMetric.selectSplitField(splitField); + + await ml.jobWizardMultiMetric.assertDetectorSplitExists(splitField); + await ml.jobWizardMultiMetric.assertDetectorSplitFrontCardTitle('FEMALE'); + await ml.jobWizardMultiMetric.assertDetectorSplitNumberOfBackCards(1); + + await ml.testExecution.logTestStep('job creation displays the influencer field'); + await ml.jobWizardCommon.assertInfluencerInputExists(); + await ml.jobWizardCommon.assertInfluencerSelection([splitField]); + + await ml.testExecution.logTestStep('job creation inputs the bucket span'); + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.setBucketSpan(bucketSpan); + + await ml.testExecution.logTestStep('job creation displays the job details step'); + await ml.jobWizardCommon.advanceToJobDetailsSection(); + + await ml.testExecution.logTestStep('job creation inputs the job id'); + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.setJobId(jobId); + + await ml.testExecution.logTestStep('job creation inputs the job description'); + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.setJobDescription(jobDescription); + + await ml.testExecution.logTestStep('job creation inputs job groups'); + await ml.jobWizardCommon.assertJobGroupInputExists(); + for (const jobGroup of jobGroups) { + await ml.jobWizardCommon.addJobGroup(jobGroup); + } + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + + await ml.testExecution.logTestStep('job creation opens the additional settings section'); + await ml.jobWizardCommon.ensureAdditionalSettingsSectionOpen(); + + await ml.testExecution.logTestStep('job creation adds a new custom url'); + await ml.jobWizardCommon.addCustomUrl({ label: 'check-kibana-dashboard' }); + + await ml.testExecution.logTestStep('job creation assigns calendars'); + await ml.jobWizardCommon.addCalendar(calendarId); + + await ml.testExecution.logTestStep('job creation opens the advanced section'); + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + + await ml.testExecution.logTestStep('job creation displays the model plot switch'); + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + + await ml.testExecution.logTestStep('job creation enables the dedicated index switch'); + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.activateDedicatedIndexSwitch(); + + await ml.testExecution.logTestStep('job creation inputs the model memory limit'); + await ml.jobWizardCommon.assertModelMemoryLimitInputExists(); + await ml.jobWizardCommon.setModelMemoryLimit(memoryLimit); + + await ml.testExecution.logTestStep('job creation displays the validation step'); + await ml.jobWizardCommon.advanceToValidationSection(); + + await ml.testExecution.logTestStep('job creation displays the summary step'); + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job creation runs the job and displays it correctly in the job list', async () => { + await ml.testExecution.logTestStep('job creation creates the job and finishes processing'); + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + + await ml.testExecution.logTestStep('job creation displays the created job in the job list'); + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.filterWithSearchString(jobId, 1); + + await ml.testExecution.logTestStep( + 'job creation displays details for the created job in the job list' + ); + await ml.jobTable.assertJobRowFields(jobId, getExpectedRow(jobId, jobGroups)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobId, + getExpectedCounts(jobId), + getExpectedModelSizeStats(jobId) + ); + + await ml.testExecution.logTestStep('job creation has detector results'); + for (let i = 0; i < detectors.length; i++) { + await ml.api.assertDetectorResultsExist(jobId, i); + } + }); + + it('job cloning opens the existing job in the geo wizard', async () => { + await ml.testExecution.logTestStep( + 'job cloning clicks the clone action and loads the geo wizard' + ); + await ml.jobTable.clickCloneJobAction(jobId); + await ml.jobTypeSelection.assertGeoJobWizardOpen(); + }); + + it('job cloning navigates through the geo wizard, checks and sets all needed fields', async () => { + await ml.testExecution.logTestStep('job cloning displays the time range step'); + await ml.jobWizardCommon.assertTimeRangeSectionExists(); + + await ml.testExecution.logTestStep('job cloning sets the time range'); + await ml.jobWizardCommon.clickUseFullDataButton( + 'Jun 12, 2019 @ 00:04:19.000', + 'Jul 12, 2019 @ 23:45:36.000' + ); + + await ml.testExecution.logTestStep('job cloning displays the event rate chart'); + await ml.jobWizardCommon.assertEventRateChartExists(); + await ml.jobWizardCommon.assertEventRateChartHasData(); + + await ml.testExecution.logTestStep('job cloning displays the pick fields step'); + await ml.jobWizardCommon.advanceToPickFieldsSection(); + + await ml.testExecution.logTestStep('job cloning pre-fills the geo field'); + await ml.jobWizardGeo.assertGeoFieldInputExists(); + await ml.jobWizardGeo.assertGeoFieldSelection([geoField]); + + await ml.testExecution.logTestStep( + 'job cloning displays the detector preview with pre-filled geo field' + ); + await ml.jobWizardGeo.assertDetectorPreviewExists(detectors[0].identifier); + + await ml.testExecution.logTestStep('job cloning pre-fills influencers'); + await ml.jobWizardCommon.assertInfluencerInputExists(); + await ml.jobWizardCommon.assertInfluencerSelection([splitField]); + + await ml.testExecution.logTestStep('job cloning pre-fills the bucket span'); + await ml.jobWizardCommon.assertBucketSpanInputExists(); + await ml.jobWizardCommon.assertBucketSpanValue(bucketSpan); + + await ml.testExecution.logTestStep('job cloning displays the job details step'); + await ml.jobWizardCommon.advanceToJobDetailsSection(); + + await ml.testExecution.logTestStep('job cloning does not pre-fill the job id'); + await ml.jobWizardCommon.assertJobIdInputExists(); + await ml.jobWizardCommon.assertJobIdValue(''); + + await ml.testExecution.logTestStep('job cloning inputs the clone job id'); + await ml.jobWizardCommon.setJobId(jobIdClone); + + await ml.testExecution.logTestStep('job cloning pre-fills the job description'); + await ml.jobWizardCommon.assertJobDescriptionInputExists(); + await ml.jobWizardCommon.assertJobDescriptionValue(jobDescription); + + await ml.testExecution.logTestStep('job cloning pre-fills job groups'); + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroups); + + await ml.testExecution.logTestStep('job cloning inputs the clone job group'); + await ml.jobWizardCommon.assertJobGroupInputExists(); + await ml.jobWizardCommon.addJobGroup('clone'); + await ml.jobWizardCommon.assertJobGroupSelection(jobGroupsClone); + + await ml.testExecution.logTestStep('job cloning opens the additional settings section'); + await ml.jobWizardCommon.ensureAdditionalSettingsSectionOpen(); + + await ml.testExecution.logTestStep('job cloning persists custom urls'); + await ml.customUrls.assertCustomUrlLabel(0, 'check-kibana-dashboard'); + + await ml.testExecution.logTestStep('job cloning persists assigned calendars'); + await ml.jobWizardCommon.assertCalendarsSelection([calendarId]); + + await ml.testExecution.logTestStep('job cloning opens the advanced section'); + await ml.jobWizardCommon.ensureAdvancedSectionOpen(); + + await ml.testExecution.logTestStep('job cloning pre-fills the model plot switch'); + await ml.jobWizardCommon.assertModelPlotSwitchExists(); + await ml.jobWizardCommon.assertModelPlotSwitchCheckedState(false); + + await ml.testExecution.logTestStep('job cloning pre-fills the dedicated index switch'); + await ml.jobWizardCommon.assertDedicatedIndexSwitchExists(); + await ml.jobWizardCommon.assertDedicatedIndexSwitchCheckedState(true); + + await ml.testExecution.logTestStep('job cloning displays the validation step'); + await ml.jobWizardCommon.advanceToValidationSection(); + + await ml.testExecution.logTestStep('job cloning displays the summary step'); + await ml.jobWizardCommon.advanceToSummarySection(); + }); + + it('job cloning runs the clone job and displays it correctly in the job list', async () => { + await ml.testExecution.logTestStep('job cloning creates the job and finishes processing'); + await ml.jobWizardCommon.assertCreateJobButtonExists(); + await ml.jobWizardCommon.createJobAndWaitForCompletion(); + + await ml.testExecution.logTestStep('job cloning displays the created job in the job list'); + await ml.navigation.navigateToMl(); + await ml.navigation.navigateToJobManagement(); + + await ml.jobTable.filterWithSearchString(jobIdClone, 1); + + await ml.testExecution.logTestStep( + 'job cloning displays details for the created job in the job list' + ); + await ml.jobTable.assertJobRowFields(jobIdClone, getExpectedRow(jobIdClone, jobGroupsClone)); + + await ml.jobTable.assertJobRowDetailsCounts( + jobIdClone, + getExpectedCounts(jobIdClone), + getExpectedModelSizeStats(jobIdClone) + ); + + await ml.testExecution.logTestStep('job cloning has detector results'); + for (let i = 0; i < detectors.length; i++) { + await ml.api.assertDetectorResultsExist(jobId, i); + } + }); + }); +} diff --git a/x-pack/test/functional/apps/ml/anomaly_detection_jobs/index.ts b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/index.ts index 96c8bd3352393..e350ced98aa79 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection_jobs/index.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection_jobs/index.ts @@ -43,6 +43,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./single_metric_job_without_datafeed_start')); loadTestFile(require.resolve('./multi_metric_job')); loadTestFile(require.resolve('./population_job')); + loadTestFile(require.resolve('./geo_job')); loadTestFile(require.resolve('./saved_search_job')); loadTestFile(require.resolve('./advanced_job')); loadTestFile(require.resolve('./categorization_job')); diff --git a/x-pack/test/functional/services/ml/index.ts b/x-pack/test/functional/services/ml/index.ts index e360bfecf3a32..4ac41a25a556e 100644 --- a/x-pack/test/functional/services/ml/index.ts +++ b/x-pack/test/functional/services/ml/index.ts @@ -36,6 +36,7 @@ import { MachineLearningJobWizardCommonProvider } from './job_wizard_common'; import { MachineLearningJobWizardCategorizationProvider } from './job_wizard_categorization'; import { MachineLearningJobWizardMultiMetricProvider } from './job_wizard_multi_metric'; import { MachineLearningJobWizardPopulationProvider } from './job_wizard_population'; +import { MachineLearningJobWizardGeoProvider } from './job_wizard_geo'; import { MachineLearningLensVisualizationsProvider } from './lens_visualizations'; import { MachineLearningNavigationProvider } from './navigation'; import { MachineLearningOverviewPageProvider } from './overview_page'; @@ -115,6 +116,7 @@ export function MachineLearningProvider(context: FtrProviderContext) { const jobWizardCommon = MachineLearningJobWizardCommonProvider(context, commonUI, customUrls); const jobWizardMultiMetric = MachineLearningJobWizardMultiMetricProvider(context); const jobWizardPopulation = MachineLearningJobWizardPopulationProvider(context); + const jobWizardGeo = MachineLearningJobWizardGeoProvider(context); const lensVisualizations = MachineLearningLensVisualizationsProvider(context, commonUI); const navigation = MachineLearningNavigationProvider(context); const overviewPage = MachineLearningOverviewPageProvider(context); @@ -174,6 +176,7 @@ export function MachineLearningProvider(context: FtrProviderContext) { jobWizardCommon, jobWizardMultiMetric, jobWizardPopulation, + jobWizardGeo, lensVisualizations, mlNodesPanel, navigation, diff --git a/x-pack/test/functional/services/ml/job_type_selection.ts b/x-pack/test/functional/services/ml/job_type_selection.ts index b17ecf3ab138a..abdf96633b1ae 100644 --- a/x-pack/test/functional/services/ml/job_type_selection.ts +++ b/x-pack/test/functional/services/ml/job_type_selection.ts @@ -34,10 +34,19 @@ export function MachineLearningJobTypeSelectionProvider({ getService }: FtrProvi await this.assertPopulationJobWizardOpen(); }, + async selectGeoJob() { + await testSubjects.clickWhenNotDisabledWithoutRetry('mlJobTypeLinkGeoJob'); + await this.assertGeoJobWizardOpen(); + }, + async assertPopulationJobWizardOpen() { await testSubjects.existOrFail('mlPageJobWizard population'); }, + async assertGeoJobWizardOpen() { + await testSubjects.existOrFail('mlPageJobWizard geo'); + }, + async selectAdvancedJob() { await testSubjects.clickWhenNotDisabledWithoutRetry('mlJobTypeLinkAdvancedJob'); await this.assertAdvancedJobWizardOpen(); diff --git a/x-pack/test/functional/services/ml/job_wizard_geo.ts b/x-pack/test/functional/services/ml/job_wizard_geo.ts new file mode 100644 index 0000000000000..3920212566932 --- /dev/null +++ b/x-pack/test/functional/services/ml/job_wizard_geo.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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export function MachineLearningJobWizardGeoProvider({ getService }: FtrProviderContext) { + const comboBox = getService('comboBox'); + const testSubjects = getService('testSubjects'); + + return { + async assertGeoFieldInputExists() { + await testSubjects.existOrFail('mlGeoFieldNameSelect > comboBoxInput'); + }, + + async assertGeoFieldSelection(expectedIdentifier: string[]) { + const comboBoxSelectedOptions = await comboBox.getComboBoxSelectedOptions( + 'mlGeoFieldNameSelect > comboBoxInput' + ); + expect(comboBoxSelectedOptions).to.eql( + expectedIdentifier, + `Expected geo field selection to be '${expectedIdentifier}' (got '${comboBoxSelectedOptions}')` + ); + }, + + async selectGeoField(identifier: string) { + await comboBox.set('mlGeoFieldNameSelect > comboBoxInput', identifier); + await this.assertGeoFieldSelection([identifier]); + }, + + async assertSplitCardWithMapExampleExists() { + await testSubjects.existOrFail('mlGeoJobWizardMap'); + }, + + async assertDetectorPreviewExists(detectorDescription: string) { + await testSubjects.existOrFail('mlGeoMap > mlDetectorTitle'); + const actualDetectorTitle = await testSubjects.getVisibleText('mlGeoMap > mlDetectorTitle'); + expect(actualDetectorTitle).to.eql( + detectorDescription, + `Expected detector title to be '${detectorDescription}' (got '${actualDetectorTitle}')` + ); + + await testSubjects.existOrFail('mlGeoJobWizardMap'); + await testSubjects.existOrFail('mlEmbeddedMapContent'); + }, + }; +} diff --git a/x-pack/test/functional/services/ml/job_wizard_multi_metric.ts b/x-pack/test/functional/services/ml/job_wizard_multi_metric.ts index 2d25144142baf..d60a5b67c4312 100644 --- a/x-pack/test/functional/services/ml/job_wizard_multi_metric.ts +++ b/x-pack/test/functional/services/ml/job_wizard_multi_metric.ts @@ -15,12 +15,12 @@ export function MachineLearningJobWizardMultiMetricProvider({ getService }: FtrP return { async assertSplitFieldInputExists() { - await testSubjects.existOrFail('mlMultiMetricSplitFieldSelect > comboBoxInput'); + await testSubjects.existOrFail('mlSplitFieldSelect > comboBoxInput'); }, async assertSplitFieldSelection(expectedIdentifier: string[]) { const comboBoxSelectedOptions = await comboBox.getComboBoxSelectedOptions( - 'mlMultiMetricSplitFieldSelect > comboBoxInput' + 'mlSplitFieldSelect > comboBoxInput' ); expect(comboBoxSelectedOptions).to.eql( expectedIdentifier, @@ -29,12 +29,12 @@ export function MachineLearningJobWizardMultiMetricProvider({ getService }: FtrP }, async selectSplitField(identifier: string) { - await comboBox.set('mlMultiMetricSplitFieldSelect > comboBoxInput', identifier); + await comboBox.set('mlSplitFieldSelect > comboBoxInput', identifier); await this.assertSplitFieldSelection([identifier]); }, async scrollSplitFieldIntoView() { - await testSubjects.scrollIntoView('mlMultiMetricSplitFieldSelect'); + await testSubjects.scrollIntoView('mlSplitFieldSelect'); }, async assertDetectorSplitExists(splitField: string) { From 584b2ff1e371d404b540d403dde45f05fe8f2ba9 Mon Sep 17 00:00:00 2001 From: Trevor Pierce <1Copenut@users.noreply.github.com> Date: Tue, 14 Feb 2023 12:04:17 -0600 Subject: [PATCH 191/203] Upgrade EUI to v75.0.0 (#150787) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary `eui@74.0.2` ⏩ `eui@75.0.0` ___ ## [`75.0.0`](https://github.com/elastic/eui/tree/v75.0.0) - `EuiFlyout`s now automatically shard all fixed `EuiHeader`s on the page. This means that interactions (mouse & keyboard) with items inside `EuiHeader`s when flyouts are open will no longer trigger focus fighting ([#6566](https://github.com/elastic/eui/pull/6566)) - `EuiFlyout`s now read out detailed screen reader dialog instructions and hints on open ([#6566](https://github.com/elastic/eui/pull/6566)) **Bug fixes** - Fixed `EuiSelectable` options with incorrect `aria-posinset` indices when rendered with group labels not at the start of the array ([#6571](https://github.com/elastic/eui/pull/6571)) - Fixed a bug with `EuiSearchBar` where filters with `multiSelect: false` were not able to select a new option when an option was already selected ([#6577](https://github.com/elastic/eui/pull/6577)) **Breaking changes** - Removed the ability to customize the `role` prop of `EuiFlyout`s. `EuiFlyout`s should always be dialog roles for screen reader consistency. ([#6566](https://github.com/elastic/eui/pull/6566)) - Removed `closeButtonAriaLabel` prop from `EuiFlyout` - use `closeButtonProps['aria-label']` instead ([#6566](https://github.com/elastic/eui/pull/6566)) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- package.json | 2 +- .../__snapshots__/collapsible_nav.test.tsx.snap | 1 + .../header/__snapshots__/header.test.tsx.snap | 2 ++ .../__snapshots__/i18n_service.test.tsx.snap | 3 +++ .../src/i18n_eui_mapping.tsx | 17 +++++++++++++++++ src/dev/license_checker/config.ts | 2 +- .../keyboard_shortcuts_doc.tsx | 2 +- .../fields/script_recorder_fields.tsx | 2 +- .../browser/script_recorder_fields.tsx | 2 +- .../apps/endpoint/trusted_apps_list.ts | 2 ++ yarn.lock | 8 ++++---- 11 files changed, 34 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 769c09752fcd6..4349bb747869e 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "@elastic/datemath": "5.0.3", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@8.6.0-canary.3", "@elastic/ems-client": "8.4.0", - "@elastic/eui": "74.1.0", + "@elastic/eui": "75.0.0", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", diff --git a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 4af92461be626..38c5a7fdf4854 100644 --- a/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/packages/core/chrome/core-chrome-browser-internal/src/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -10,6 +10,7 @@ Array [

    =68fcoNxD1ObZghLRlQod%HdX?8QdsOpNAJ zQQ|-+#@R|a0ly}jGJ(7vnkpvEtO~k9GU-yVke`67=4n{+{__Ni5Qh;nqyDqS; zMtJRa#SgZrD_4Kb0XPFp`&}Z_d@Qd#>EFw{wl-@rH}ar~#!9Z1G?=ee~i zL;lGvkSxu{@O>cDL5Ybl&9yRTMYhA9oNj{Kh1860-fCLRMpoA!hXM`C*Rq*B4!~y5 zhjPe#B@f!2(Qqg|vA}>;3T${Kt1XrSc|9qniRz+4Sq^obFcV)aD#B*dkt4$t90M6A z`9}VIdF~f`%(fMM7k(GAJDSqexjm{P@Texl5he>lE%ki#q33FwQHfsbYO|nq-7z&) zkoLZ5O>|i0VCRGC`x4B{seMecjpFep%tS`IFE0^=aGY7PWY#p+U>b(Er zVRMd^7uf;2;gaO~s_NO^RK-iqE)KQXOg`rys1HX!D^_dXh14?dUv7}>d;k!JnEC@= zvo_S+@25@_^=RlVyaI!2NU-(Rj`j=q0>1cMdA2J4!krKnRx0jFsr%v&?w1`n5DN9q zU+?(snH49jnf;1)1`O}G$m{h^S)p6=H&vUVbHn@_zx(^n-p@1M9x#9+X%%KLLZb?C?iinD8#a7a zP_FrK_jU7GV~$Qu#pM@SXfYX(ziqK=s?&Y55vF<9ic93n>#+h183S#ogYTuaylso# zHw%wkuBMs}lHZrJVLPtjw#apPa3vcVcP~&I1cr|$KAq){`RQ(RjOqgWUclu^=_yGL zr)#g?zQBFC7Jn%btvTb!Z6Z-idh z#eh(zU9u(wuHX4&sMppv80!s-f;MPvOxGV zfkwh1miywMY|{50E-{YBCvLmB-bc1y_p<7?zS8EW0-qIzl#3M=^k1aB`~}#qcloeO z^yzdJ=y*EDkfLmPR~k;cB(+tBq&(;Zch9Gq<4^MAUK7ggDsc27?x=H*u3uBOJEK@bUuwX>cp@6xL_PTViaS1s#+`IUp;RFt6ZkPD z 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 H_oDtE$gH;t literal 195119 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ǰ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